在下面给出的代码中,foo1
和foo2
的类型推断之间有什么区别:
interface myInterface {
foo1(args: string): void;
foo2: (args: string) => void;
}
两者的类型推断是否不同?还有什么时候用哪个?
答案 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。