界面内部箭头功能与普通功能之间的区别

时间:2019-02-26 11:27:44

标签: typescript

在下面给出的代码中,foo1foo2的类型推断之间有什么区别:

interface myInterface {
    foo1(args: string): void;
    foo2: (args: string) => void;
}

两者的类型推断是否不同?还有什么时候用哪个?

2 个答案:

答案 0 :(得分:3)

在接口中,几乎没有区别。您可以根据自己的喜好混合和匹配两种样式:

interface myInterface {
    foo1(args: string): void;
    foo2: (args: string) => void;
}

class C implements myInterface {
    foo1: (args: string) => void = (args) => {

    }

    foo2(args: string) {

    }
}

此外,两者在运行时都可以完全互换:

declare const i: myInterface;

const c = new C;

// no errors
c.foo1 = i.foo2;
i.foo1 = c.foo2;
c.foo2 = i.foo1;
i.foo2 = c.foo1;

影响类型推断有一个区别:--strictFunctionTypes标志不适用于方法,因此在严格模式下,当参数和返回类型不同时,方法和函数属性具有不同的兼容性规则。

另一个区别是您可以将属性声明为只读,以防止分配给它。您无法使用方法来做到这一点(但仍然可以使用Readonly<myInterface>声明另一种类型,该类型会将所有属性和方法都设为只读)。

interface myInterface {
    foo1(args: string): void;
    readonly foo2: (args: string) => void;
}

i.foo2 = c.foo1; // this is an error now

但是,在类中,它们是不同的,可能是因为方法是在运行时在类原型对象上定义的,但是属性是在为构造函数生成的代码中初始化的,因此无法用方法覆盖属性:

class C2 extends C {

    foo1(args: string) { // error:  Class 'C' defines instance member property 'foo1',
                        // but extended class 'C2' defines it as instance member function.

    }

    foo2: (args: string) => void = (args) => { // Ok

    }

}

答案 1 :(得分:1)

尽管两个定义在类型级别上都相同,但是箭头类功能不能在运行时与方法互换。

简而言之,方法是继承的,而类属性字段则不是。有关更多详细信息,请参见this answer