这个问题直接类似于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;
}

其他回答

另一种解决方案可能与HTMLIFrameElement接口的情况类似。如果我们知道在另一个模块中有它的实现,我们可以通过在接口旁边创建一个对象来声明一个同名的变量。

declare var HTMLIFrameElement: {
    prototype: HTMLIFrameElement;
    new(): HTMLIFrameElement;
};

在这种情况下

interface A {
    member:string;
}

declare var A : {
    prototype: A;
    new(): A;
};

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

应该没问题

你可以在运行时使用ts-validate-type验证TypeScript类型,就像这样(确实需要一个Babel插件):

const user = validateType<{ name: string }>(data);

使用字符串文字是很困难的,因为如果你想重构你的方法或接口名称,那么你的IDE可能不重构这些字符串文字。 我为您提供我的解决方案,如果在接口中至少有一个方法

export class SomeObject implements interfaceA {
  public methodFromA() {}
}

export interface interfaceA {
  methodFromA();
}

检查object是否为interface类型:

const obj = new SomeObject();
const objAsAny = obj as any;
const objAsInterfaceA = objAsAny as interfaceA;
const isObjOfTypeInterfaceA = objAsInterfaceA.methodFromA != null;
console.log(isObjOfTypeInterfaceA)

注意:即使我们删除了'implements interfaceA',我们也会得到true,因为SomeObject类中仍然存在该方法

TypeGuards

interface MyInterfaced {
    x: number
}

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

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

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

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

var obj : any = new Foo();

if (obj.someInterfaceMethod) {
    ...
}