I have the following classes & interfaces:
export interface IBody {
body : ListBody;
}
export class Element {
// ...
}
export class Paragraph extends Element implements IBody {
// ...
}
export class Character extends Element {
// ...
}
I have code where I will get an array of Element derived objects (there are more than just Paragraph & Character). In the case of those that implement IBody, I need to take action on the elements in the body.
What is the best way to see if it implements IBody? Is it "if (element.body !== undefined)"?
And then how do I access it? "var bodyElement = <IBody> element;" gives me an error.
C:/src/jenova/Dev/Merge/AutoTagWeb/client/layout/document/elements/factory.ts(34,27): error TS2012: Cannot convert 'Element' to 'IBody':
Type 'Element' is missing property 'body' from type 'IBody'.
Type 'IBody' is missing property 'type' from type 'Element'.
thanks - dave
An interface
in TypeScript is a compile-time only construct, with no run-time representation. You might find section 7 of the TypeScript specification interesting to read as it has the complete details.
So, you can't "test" for an interface
specifically. Done correctly and completely, you generally shouldn't need to test for it as the compiler should have caught the cases where an object didn't implement the necessary interface. If you were to try using a type assertion:
// // where e has been typed as any, not an Element
var body = <IBody> e;
The compiler will allow it without warning as you've asserted that the type is an IBody
. If however, e
were an Element
in scope, the compiler as you've shown will check the signature of the Element
and confirm that it has the properties/methods declared by IBody
. It's important to note that it's checking the signature -- it doesn't matter that it may not implement IBody
as long as the signature matches up.
Assuming that Element
has a signature that matches IBody
, it will work. If it does not, you'll get the compiler error you're receiving. But, again, if it's declared as any
, the assertion will pass and at run-time, unless the type has the methods defined on IBody
, the script will fail.
As your Element
is the base class, you cannot check for IBody
. You could declare an argument as any
:
function someFeature(e: any) {
}
And then assert that the IBody
is present:
function someFeature(e: any) {
var body :IBody = <IBody> e;
// do something
}
However, if you do need a run-time check, you'd need to look for the function on the prototype
or as a property before using it. While that could be misleading in some cases, the interface
in TypeScript also may not have caught the mismatch either. Here's an example of how you could check for the existence of a specific function.
It might look like this:
function someFeature(e: any) {
var body = <IBody> e;
if (typeof (body.someFunctionOnBodyInterface) === "undefined") {
// not safe to use the function
throw new Error("Yikes!");
}
body.someFunctionOnBodyInterface();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With