【问题标题】:How do I cast to an interface an object may implement?如何转换为对象可以实现的接口?
【发布时间】:2014-04-25 00:02:57
【问题描述】:

我有以下类和接口:

export interface IBody {
    body : ListBody;
}

export class Element  {
// ...
}

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

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

我有代码,我将在其中获取元素派生对象的数组(不仅仅是段落和字符)。对于那些实现 IBody 的情况,我需要对 body 中的元素采取行动。

查看它是否实现 IBody 的最佳方法是什么?是“if (element.body !== undefined)”吗?

然后我如何访问它? "var bodyElement = 元素;"给我一个错误。

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

谢谢 - 戴夫

【问题讨论】:

    标签: interface typescript


    【解决方案1】:

    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 也可能没有发现不匹配的情况。 Here 是一个如何检查特定函数是否存在的示例。

    它可能看起来像这样:

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

    【讨论】:

    • 很好的答案,但是强调 typescript 是结构化类型的事实可能会很好。那是;接口 IFoo { a: 数字; } 被认为是与 IBar { a: number; 相同的“类型”。 },即接受 IFoo 的函数也将愉快地接受 IBar。
    • OK -- 我更新了问题以更好地解释类型断言失败的原因,并在进行断言时修复了有关预期类型的​​重要错字。而且,我在底部包含的链接对如何检查函数/属性的存在有很好的建议。
    • 现在有一个来自 Victor Savkin 的库,用于运行时类型检查:npmjs.com/package/runtime-type-checks
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-31
    • 1970-01-01
    • 2013-02-02
    • 2019-05-08
    • 2015-04-11
    相关资源
    最近更新 更多