这个问题直接类似于TypeScript中的类类型检查

我需要在运行时找出任何类型的变量是否实现了接口。这是我的代码:

interface A{
    member:string;
}

var a:any={member:"foobar"};

if(a instanceof A) alert(a.member);

如果您在typescript游乐场中输入这段代码,最后一行将被标记为错误,“名称A不存在于当前作用域”。但事实并非如此,该名称确实存在于当前作用域中。我甚至可以更改变量声明为var a: a ={成员:"foobar"};没有编辑的抱怨。在浏览网页并找到其他问题后,我将接口更改为类,但我不能使用对象字面量来创建实例。

我想知道A类型是如何消失的,但看看生成的javascript就能解释这个问题:

var a = {
    member: "foobar"
};
if(a instanceof A) {
    alert(a.member);
}

没有将A表示为接口,因此不可能进行运行时类型检查。

我知道javascript作为一种动态语言没有接口的概念。是否有方法对接口进行类型检查?

typescript游乐场的自动完成显示typescript甚至提供了一个方法实现。我怎么使用它?


当前回答

TypeGuards

interface MyInterfaced {
    x: number
}

function isMyInterfaced(arg: any): arg is MyInterfaced {
    return arg.x !== undefined;
}

if (isMyInterfaced(obj)) {
    (obj as MyInterfaced ).x;
}

其他回答

简单的解决方案,与所选的解决方案有相同的缺点,但这个变体捕捉JS错误,只接受对象作为参数,并有一个有意义的返回值。

interface A{
    member:string;
}

const implementsA = (o: object): boolean => {
    try {
        return 'member' in o;
    } catch (error) {
        return false;
    }
}

const a:any={member:"foobar"};

implementsA(a) && console.log("a implements A");
// implementsA("str"); // causes TS transpiler error

你也可以向子组件发送多个输入,其中一个是鉴别器,另一个是实际数据,并检查子组件中的鉴别器,如下所示:

@Input() data?: any;
@Input() discriminator?: string;

ngOnInit(){
    if(this.discriminator = 'InterfaceAName'){
      //do stuff
    }
    else if(this.discriminator = 'InterfaceBName'){
      //do stuff
    }
}

显然,你可以把它移动到任何它适用的地方,比如ngOnChanges函数或setter函数,但这个想法仍然成立。如果你想要一个响应式表单,我还建议尝试将ngModel绑定到输入数据上。你可以使用这些if语句根据传入的数据来设置ngModel,并在html中反映:

<div [(ngModel)]={{dataModel}}>
    <div *ngFor="let attr of (data | keyvalue)">
        <!--You can use attr.key and attr.value in this situation to display the attributes of your interface, and their associated values from the data -->
    </div>
</div>

或者用这个代替:

<div *ngIf = "model == 'InterfaceAName'">
    <div>Do This Stuff</div>
</div>
<div *ngIf= "model == 'IntefaceBName'">
    <div>Do this instead</div>
</div>

(您可以使用attr。键和attr。值在这种情况下显示接口的属性,以及它们从数据中关联的值)

我知道这个问题已经有了答案,但我认为这可能对试图构建半模糊的角形式的人有用。你也可以将此用于角材料模块(例如对话框),通过数据参数发送两个变量——一个是你的实际数据,另一个是判别器,并通过类似的过程检查它。最终,这将允许您创建一个表单,并围绕流入其中的数据塑造表单。

你可以在没有instanceof关键字的情况下实现你想要的,因为你现在可以编写自定义类型保护:

interface A {
    member: string;
}

function instanceOfA(object: any): object is A {
    return 'member' in object;
}

var a: any = {member: "foobar"};

if (instanceOfA(a)) {
    alert(a.member);
}

会员众多

如果需要检查大量成员以确定对象是否与您的类型匹配,则可以添加标识符。下面是最基本的示例,并要求您管理自己的鉴别器…您需要深入了解模式,以确保避免重复标识符。

interface A {
    discriminator: 'I-AM-A';
    member: string;
}

function instanceOfA(object: any): object is A {
    return object.discriminator === 'I-AM-A';
}

var a: any = {discriminator: 'I-AM-A', member: "foobar"};

if (instanceOfA(a)) {
    alert(a.member);
}

我想指出的是,TypeScript并没有提供直接的机制来动态测试一个对象是否实现了特定的接口。

相反,TypeScript代码可以使用JavaScript技术来检查对象上是否存在适当的成员集。例如:

var obj : any = new Foo();

if (obj.someInterfaceMethod) {
    ...
}

现在这是可能的,我刚刚发布了一个增强版的TypeScript编译器,它提供了完整的反射功能。您可以从类的元数据对象实例化类,从类构造函数检索元数据,并在运行时检查接口/类。你可以在这里查看

使用的例子:

在你的一个typescript文件中,创建一个接口和一个实现它的类,如下所示:

interface MyInterface {
    doSomething(what: string): number;
}

class MyClass implements MyInterface {
    counter = 0;

    doSomething(what: string): number {
        console.log('Doing ' + what);
        return this.counter++;
    }
}

现在让我们打印一些已实现接口的列表。

for (let classInterface of MyClass.getClass().implements) {
    console.log('Implemented interface: ' + classInterface.name)
}

使用reflect -ts编译并启动它:

$ node main.js
Implemented interface: MyInterface
Member name: counter - member kind: number
Member name: doSomething - member kind: function

有关接口元类型的详细信息,请参阅reflect .d.ts。

更新: 您可以在这里找到一个完整的工作示例