为什么这个箭头函数在接口中无法编译?
Why does this arrow function in an interface not compile?
箭头函数和常规函数有什么区别 在实现接口中,因此代码 A 导致编译时错误,代码 B 编译成功。
注意:在 tsconfig.json
中启用了所有严格类型检查选项,包括 strictFunctionTypes
,顺便说一句,它假设通过启用 strict
所有严格类型检查选项都会启用。
导致编译时错误的代码A
interface SomeInterface {
someFunction: (par1: string | undefined) => string;
}
class SomeClass implements SomeInterface {
someFunction(par1: string): string //invalid function signature
{
throw new Error('Method not implemented.');
}
}
并且,编译成功的代码 B。
interface SomeInterface {
someFunction(par1: string | undefined): string;
}
class SomeClass implements SomeInterface {
someFunction(par1: string): string //invalid function signature
{
throw new Error("Method not implemented.");
}
}
使用 --strictFunctionTypes
enabled, function types' parameters are checked contravariantly,根据需要维护类型安全:
class SomeClass implements SomeInterface { // error here
someFunction(par1: string): string
{
return par1.toUpperCase();
}
}
const i: SomeInterface = new SomeClass(); // error here
i.someFunction(undefined); // runtime error here, par1 is undefined
但是,如文档中所述:
During development of this feature, we discovered a large number of inherently unsafe class hierarchies, including some in the DOM. Because of this, the setting only applies to functions written in function syntax, not to those in method syntax.
所以方法类型'参数仍然被检查bivariantly, meaning both contavariantly and covariantly, in order to support some common patterns (although perhaps generics or polymorphic this
would be a better way to do it for some of these cases). The big example is Array<T>
, where people apparently like their covariant arrays:
interface Animal { species: string }
interface Dog extends Animal { bark(): void };
const scooby: Dog = { species: "dog", bark() { console.log("ROOBY ROO or whatevz") } };
const snoopy: Dog = { species: "dog", bark() { console.log("...") } };
function processAnimals(arr: Animal[]) {
console.log("I got " + arr.map(x => x.species).join(", ") + ".")
};
const dogs = [scooby, snoopy];
processAnimals(dogs); // okay
这是符合人体工程学的并且很常见,但从技术上讲,编译器应该拒绝 dogs
,因为 Dog[]
不是有效的 Animal[]
(实际上,像 push()
这样的方法可以诸如将 Cat
推入引擎盖下的 Dog[]
之类的坏事)。但是如果你沿着这条路走下去,你会发现 TypeScript 就是这样到处都是不健全的,即使没有函数参数,因为 属性 写也是这样。有关详细信息,请参阅 。
并且 意味着您的 SomeClass2
不会产生错误,因为 SomeInterface2
使用方法语法:
class SomeClass2 implements SomeInterface2 { // no error
someFunction(par1: string): string {
return par1.toUpperCase();
}
}
当然这和以前有完全一样的健全性问题:
const i2: SomeInterface2 = new SomeClass2(); // no error
i2.someFunction(undefined); // runtime error, par1 is undefined
但事实就是如此。为方便起见,方法在设计上不如函数安全。
箭头函数和常规函数有什么区别 在实现接口中,因此代码 A 导致编译时错误,代码 B 编译成功。
注意:在 tsconfig.json
中启用了所有严格类型检查选项,包括 strictFunctionTypes
,顺便说一句,它假设通过启用 strict
所有严格类型检查选项都会启用。
导致编译时错误的代码A
interface SomeInterface {
someFunction: (par1: string | undefined) => string;
}
class SomeClass implements SomeInterface {
someFunction(par1: string): string //invalid function signature
{
throw new Error('Method not implemented.');
}
}
并且,编译成功的代码 B。
interface SomeInterface {
someFunction(par1: string | undefined): string;
}
class SomeClass implements SomeInterface {
someFunction(par1: string): string //invalid function signature
{
throw new Error("Method not implemented.");
}
}
使用 --strictFunctionTypes
enabled, function types' parameters are checked contravariantly,根据需要维护类型安全:
class SomeClass implements SomeInterface { // error here
someFunction(par1: string): string
{
return par1.toUpperCase();
}
}
const i: SomeInterface = new SomeClass(); // error here
i.someFunction(undefined); // runtime error here, par1 is undefined
但是,如文档中所述:
During development of this feature, we discovered a large number of inherently unsafe class hierarchies, including some in the DOM. Because of this, the setting only applies to functions written in function syntax, not to those in method syntax.
所以方法类型'参数仍然被检查bivariantly, meaning both contavariantly and covariantly, in order to support some common patterns (although perhaps generics or polymorphic this
would be a better way to do it for some of these cases). The big example is Array<T>
, where people apparently like their covariant arrays:
interface Animal { species: string }
interface Dog extends Animal { bark(): void };
const scooby: Dog = { species: "dog", bark() { console.log("ROOBY ROO or whatevz") } };
const snoopy: Dog = { species: "dog", bark() { console.log("...") } };
function processAnimals(arr: Animal[]) {
console.log("I got " + arr.map(x => x.species).join(", ") + ".")
};
const dogs = [scooby, snoopy];
processAnimals(dogs); // okay
这是符合人体工程学的并且很常见,但从技术上讲,编译器应该拒绝 dogs
,因为 Dog[]
不是有效的 Animal[]
(实际上,像 push()
这样的方法可以诸如将 Cat
推入引擎盖下的 Dog[]
之类的坏事)。但是如果你沿着这条路走下去,你会发现 TypeScript 就是这样到处都是不健全的,即使没有函数参数,因为 属性 写也是这样。有关详细信息,请参阅
并且 意味着您的 SomeClass2
不会产生错误,因为 SomeInterface2
使用方法语法:
class SomeClass2 implements SomeInterface2 { // no error
someFunction(par1: string): string {
return par1.toUpperCase();
}
}
当然这和以前有完全一样的健全性问题:
const i2: SomeInterface2 = new SomeClass2(); // no error
i2.someFunction(undefined); // runtime error, par1 is undefined
但事实就是如此。为方便起见,方法在设计上不如函数安全。