以打字稿接口类型检查(Interface type check with Typescript)

2019-07-18 10:58发布

这个问题是直接analogon到与打字稿类类型检查

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

interface A{
    member:string;
}

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

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

如果您在打字稿操场输入验证码,最后一行将被标记为错误,“名称的并不在目前的范围中不存在”。 但事实并非如此,这个名字确实在目前的范围存在。 我甚至可以改变变量声明var a:A={member:"foobar"}; 未经编辑的抱怨。 浏览网页和SO寻找其他的问题后,我改变了接口的类,但我就不能使用对象文本创建实例。

我想知道A型如何能消失一样,但一看生成的JavaScript解释的问题:

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

有作为一个接口没有A的表示,因此没有运行时类型检查是可能的。

据我所知,JavaScript作为一种动态语言没有接口的概念。 有什么办法输入支票接口?

该打字稿操场的自动完成发现,打字稿甚至提供了方法implements 。 我如何使用它?

Answer 1:

你可以达到你想要的东西没有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);
}


Answer 2:

在打字稿1.6, 用户定义类型后卫将做的工作。

interface Foo {
    fooProperty: string;
}

interface Bar {
    barProperty: string;
}

function isFoo(object: any): object is Foo {
    return 'fooProperty' in object;
}

let object: Foo | Bar;

if (isFoo(object)) {
    // `object` has type `Foo`.
    object.fooProperty;
} else {
    // `object` has type `Bar`.
    object.barProperty;
}

而且,正如乔洋提到:自打字稿2.0,你甚至可以采取标签联合型的优势。

interface Foo {
    type: 'foo';
    fooProperty: string;
}

interface Bar {
    type: 'bar';
    barProperty: number;
}

let object: Foo | Bar;

// You will see errors if `strictNullChecks` is enabled.
if (object.type === 'foo') {
    // object has type `Foo`.
    object.fooProperty;
} else {
    // object has type `Bar`.
    object.barProperty;
}

并与工作switch了。



Answer 3:

打字稿2.0介绍标签联合

打字稿2.0功能

interface Square {
    kind: "square";
    size: number;
}

interface Rectangle {
    kind: "rectangle";
    width: number;
    height: number;
}

interface Circle {
    kind: "circle";
    radius: number;
}

type Shape = Square | Rectangle | Circle;

function area(s: Shape) {
    // In the following switch statement, the type of s is narrowed in each case clause
    // according to the value of the discriminant property, thus allowing the other properties
    // of that variant to be accessed without a type assertion.
    switch (s.kind) {
        case "square": return s.size * s.size;
        case "rectangle": return s.width * s.height;
        case "circle": return Math.PI * s.radius * s.radius;
    }
}


Answer 4:

如何自定义类型逆天? https://www.typescriptlang.org/docs/handbook/advanced-types.html

interface Bird {
    fly();
    layEggs();
}

interface Fish {
    swim();
    layEggs();
}

function isFish(pet: Fish | Bird): pet is Fish { //magic happens here
    return (<Fish>pet).swim !== undefined;
}

// Both calls to 'swim' and 'fly' are now okay.

if (isFish(pet)) {
    pet.swim();
}
else {
    pet.fly();
}


Answer 5:

它现在有可能,我刚刚发布了一个增强版本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)
}

用反光贴-TS编译并启动它:

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

见reflection.d.ts Interface的元类型的详细信息。

UPDATE:你可以找到一个完整的工作示例在这里



Answer 6:

下面是另一个选项:模块TS-接口建设者提供了一个构建时的工具,一个打字稿接口转换成一个运行时描述符,和TS-接口检查可以检查一个对象是否满足它。

对于OP的例子,

interface A {
  member: string;
}

你会先运行ts-interface-builder产生一个新的简洁的文件与描述符,比如, foo-ti.ts ,您可以使用这样的:

import fooDesc from './foo-ti.ts';
import {createCheckers} from "ts-interface-checker";
const {A} = createCheckers(fooDesc);

A.check({member: "hello"});           // OK
A.check({member: 17});                // Fails with ".member is not a string" 

您可以创建一个班轮型保护功能:

function isA(value: any): value is A { return A.test(value); }


Answer 7:

我想指出的是,打字稿不用于动态测试对象是否实现特定的接口提供了直接的机制。

相反,打字稿代码可以使用检查适当的一组成员是否存在于对象上的JavaScript的技术。 例如:

var obj : any = new Foo();

if (obj.someInterfaceMethod) {
    ...
}


Answer 8:

TypeGuards

interface MyInterfaced {
    x: number
}

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

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


Answer 9:

与上述相同,其中用户定义的防护装置是使用,但这次用箭头功能谓词

interface A {
  member:string;
}

const check = (p: any): p is A => p.hasOwnProperty('member');

var foo: any = { member: "foobar" };
if (check(foo))
    alert(foo.member);


文章来源: Interface type check with Typescript