【问题标题】:Class type check in TypeScriptTypeScript 中的类类型检查
【发布时间】:2012-09-29 03:31:26
【问题描述】:

在 ActionScript 中,可以使用 is operator 在运行时检查类型:

var mySprite:Sprite = new Sprite(); 
trace(mySprite is Sprite); // true 
trace(mySprite is DisplayObject);// true 
trace(mySprite is IEventDispatcher); // true

是否可以通过 TypeScript 检测变量(扩展或)是否是某个类或接口?

我在语言规范中找不到任何关于它的信息。在使用类/接口时它应该在那里。

【问题讨论】:

    标签: typescript typechecking


    【解决方案1】:

    您可以为此使用instanceof 运算符。来自 MDN:

    instanceof 操作符测试一个对象的原型属性是否 构造函数出现在对象原型链中的任何位置。

    如果您不知道原型和原型链是什么,我强烈建议您查一下。这里还有一个 JS(TS 在这方面的工作方式类似)示例,可以阐明这个概念:

        class Animal {
            name;
        
            constructor(name) {
                this.name = name;
            }
        }
        
        const animal = new Animal('fluffy');
        
        // true because Animal in on the prototype chain of animal
        console.log(animal instanceof Animal); // true
        // Proof that Animal is on the prototype chain
        console.log(Object.getPrototypeOf(animal) === Animal.prototype); // true
        
        // true because Object in on the prototype chain of animal
        console.log(animal instanceof Object); 
        // Proof that Object is on the prototype chain
        console.log(Object.getPrototypeOf(Animal.prototype) === Object.prototype); // true
        
        console.log(animal instanceof Function); // false, Function not on prototype chain
        
        

    本例中的原型链为:

    动物 > Animal.prototype > Object.prototype

    【讨论】:

      【解决方案2】:

      4.19.4 The instanceof operator

      instanceof 运算符要求左操作数为 Any 类型、对象类型或类型参数类型,右操作数为 Any 类型或“函数”接口类型的子类型。结果始终是布尔原始类型。

      所以你可以使用

      mySprite instanceof Sprite;
      

      请注意,此运算符也在 ActionScript 中,但不应再在那里使用:

      ActionScript 3.0 新增的 is 运算符允许您测试变量或表达式是否是给定数据类型的成员。在先前版本的 ActionScript 中,instanceof 运算符提供了此功能,但在 ActionScript 3.0 中,instanceof 运算符不应用于测试数据类型成员资格。应该使用 is 运算符而不是 instanceof 运算符进行手动类型检查,因为表达式 x instanceof y 仅检查 x 的原型链是否存在 y(在 ActionScript 3.0 中,原型链不提供继承层次结构)。

      TypeScript 的instanceof 也有同样的问题。由于它是一种仍在开发中的语言,因此我建议您提出这种设施的建议。

      另见:

      【讨论】:

        【解决方案3】:

        TypeScript 有一种在运行时验证变量类型的方法。 您可以添加一个返回类型谓词的验证函数。 因此,您可以在 if 语句中调用此函数,并确保该块中的所有代码都可以安全地用作您认为的类型。

        TypeScript 文档中的示例:

        function isFish(pet: Fish | Bird): pet is Fish {
           return (<Fish>pet).swim !== undefined;
        }
        
        // Both calls to 'swim' and 'fly' are now okay.
        if (isFish(pet)) {
          pet.swim();
        }
        else {
          pet.fly();
        }
        

        查看更多信息: https://www.typescriptlang.org/docs/handbook/advanced-types.html

        【讨论】:

        • 这不是运行时类型检查,它只是检查对象是否具有特定属性。这对于联合类型可能很好,因此适用于这种特定情况,但为这样的所有内容创建“isThingy”并不是真正可行的。此外,如果鱼和鸟都可以游泳,那么你注定要失败。我很高兴我正在使用 Haxe,它具有可靠的类型检查功能,因此您可以执行 Std.is(pet, Fish),它适用于类型、接口等。
        • 我发现这个答案很有帮助,但我认为您可以将其调整得更精确一些。 isFish 本身就是创建的谓词,它的主体不必是单行谓词。这样做的好处是编译器在编译时理解适当的可能函数,但您在isFish 中的代码是在运行时执行的。你甚至可以让守卫包含一个instanceof 声明,例如return pet instanceof Fish(假设它是一个类而不是接口),但这是不必要的,因为编译器直接理解 instanceof
        • 这也称为“用户定义的类型保护”,见basarat.gitbooks.io/typescript/content/docs/types/…
        • @MarkKnol 它实际上是运行时检查,但也为打字稿带来了理解推断类型的能力(意思是:你可以相信我这将是 X 或 Y 类型,因为我将在运行时对其进行测试)。
        • 您可能需要考虑使用(pet as Fish),因为 tslinter 会抱怨(&lt;Fish&gt;pet)。见tslint doc
        猜你喜欢
        • 2021-11-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多