如何将对象转换为可能实现的接口?

8

我有以下类和接口:

export interface IBody {
    body : ListBody;
}

export class Element  {
// ...
}

export class Paragraph extends Element implements IBody {
// ...
}

export class Character extends Element {
// ...
}

我有一段代码,其中将获取Element派生对象的数组(不仅仅是段落和字符)。对于那些实现了IBody接口的对象,我需要在其Body中执行操作。

如何最好地判断它是否实现了IBody接口?是使用 "if (element.body !== undefined)" 吗?

然后我该如何访问它呢? "var bodyElement = <IBody> element;" 给出了一个错误。

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'.

感谢 - Dave
1个回答

26
在 TypeScript 中,interface 是一种仅存在于编译时的结构,没有运行时的表示。你可能会发现 TypeScript 规范的第 7 节很有趣,因为它包含了完整的细节。
所以,你不能专门“测试”一个 interface。如果正确而完整地完成,你通常不需要测试它,因为编译器应该已经捕获了对象未实现必要接口的情况。如果您尝试使用类型断言:
// // where e has been typed as any, not an Element
var body = <IBody> e; 
编译器将允许此操作而不发出警告,因为您已断言该类型是IBody。然而,如果作用域中的e是一个Element,则编译器将会检查Element的签名,并确认其具有被IBody声明的属性/方法。需要注意的是,它检查的是签名--只要签名匹配,它就不在意是否实现了IBody
假设Element的签名与IBody相匹配,那么就可以工作。如果不匹配,则会收到编译器错误。但是,如果声明为any,则断言将通过,并且在运行时,除非该类型定义了IBody上的方法,否则脚本将失败。
由于您的Element是基类,因此无法检查IBody。您可以将参数声明为any:
function someFeature(e: any) {

} 

然后断言IBody存在:

function someFeature(e: any) {
     var body :IBody = <IBody> e;    
     // do something
} 

然而,如果你需要运行时检查,你需要在使用函数之前查找prototype上的函数或作为属性。虽然在某些情况下这可能会引起误导,但TypeScript中的interface也可能没有捕获到不匹配的情况。 这里有一个如何检查特定函数存在性的示例。

它可能看起来像这样:

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();
}

4
不错的答案,但最好强调TypeScript是结构类型化的。也就是说,接口IFoo {a:number;}被认为与IBar {a:number;}是相同的“类型”,即接受IFoo的函数也会欣然接受IBar。 - Nypan
好的--我更新了问题,更好地解释了为什么类型断言失败,并修正了关于断言时预期类型的一个重要错别字。而且,我在底部包含的链接提供了一个很好的建议,可以检查函数/属性是否存在。 - WiredPrairie
现在Victor Savkin提供了一个运行时类型检查的库:https://www.npmjs.com/package/runtime-type-checks - Bruno Garcia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接