如何获得 TypeScript 中返回函数的类型安全性?
How can I get type safety for returned functions in TypeScript?
这个 TypeScript 编译得很好:
abstract class Animal {
/*
Any extension of Animal MUST have a function which returns
another function that has exactly the signature (string): void
*/
abstract getPlayBehavior(): (toy: string) => void;
}
class Cat extends Animal {
/*
Clearly does not have a function which returns a function
that has the correct signature. This function returns a function with
the signature (void) : void
*/
getPlayBehavior() {
return () => {
console.log(`Play with toy_var_would_go_here!`);
};
}
}
class Program {
static main() {
let cat: Animal = new Cat();
cat.getPlayBehavior()("Toy");
}
}
Program.main();
我预计会出现错误,因为猫 class 绝对没有实现抽象动物 class 正确地。我希望 Cat class 必须有一个函数 returns 抽象 Animal class.
中指定的确切签名的另一个函数
运行代码,我得到:
> node index.js
> Play with toy_var_would_go_here!
我能做些什么来确保编译器执行这种策略吗?
I am expecting an error because the Cat class definitely does not implement the abstract Animal class properly
因为类型兼容性。一个不接受任何参数的函数(比如foo
)可以分配给一个接受参数的函数(比如bar
)。
原因:bar
没有用法,foo
运行所需的所有信息都将不存在。
更多
您不会收到错误,因为在 javascript/typescript 中,如果您不想使用参数,则不会强制声明它们,只要不存在矛盾即可。
例如Array.forEach的签名是:
forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void;
但这会编译得很好:
let a = [1, 2, 3];
a.forEach(item => console.log(item));
这是一件好事,如果我必须拥有所有参数,即使我不使用它们,那也太可怕了。
这里也是如此:
type MyFn = (s: string) => void;
let fn: MyFn = () => console.log("hey");
如果我不需要使用字符串参数那么我可以忽略它,或者我什至可以这样做:
let fn: MyFn = () => console.log(arguments);
如果您将 Cat.getPlayBehavior
中 return 的函数签名更改为与 Animal
中的定义相矛盾的东西,那么您将得到一个错误:
class Cat extends Animal {
getPlayBehavior() {
return (n: number) => {
console.log(`Play with toy_var_would_go_here!`);
};
}
}
错误:
Class 'Cat' incorrectly extends base class 'Animal'.
Types of property 'getPlayBehavior' are incompatible.
Type '() => (n: number) => void' is not assignable to type '() => (toy: string) => void'.
Type '(n: number) => void' is not assignable to type '(toy: string) => void'.
Types of parameters 'n' and 'toy' are incompatible.
Type 'string' is not assignable to type 'number'.
这个 TypeScript 编译得很好:
abstract class Animal {
/*
Any extension of Animal MUST have a function which returns
another function that has exactly the signature (string): void
*/
abstract getPlayBehavior(): (toy: string) => void;
}
class Cat extends Animal {
/*
Clearly does not have a function which returns a function
that has the correct signature. This function returns a function with
the signature (void) : void
*/
getPlayBehavior() {
return () => {
console.log(`Play with toy_var_would_go_here!`);
};
}
}
class Program {
static main() {
let cat: Animal = new Cat();
cat.getPlayBehavior()("Toy");
}
}
Program.main();
我预计会出现错误,因为猫 class 绝对没有实现抽象动物 class 正确地。我希望 Cat class 必须有一个函数 returns 抽象 Animal class.
中指定的确切签名的另一个函数运行代码,我得到:
> node index.js
> Play with toy_var_would_go_here!
我能做些什么来确保编译器执行这种策略吗?
I am expecting an error because the Cat class definitely does not implement the abstract Animal class properly
因为类型兼容性。一个不接受任何参数的函数(比如foo
)可以分配给一个接受参数的函数(比如bar
)。
原因:bar
没有用法,foo
运行所需的所有信息都将不存在。
更多
您不会收到错误,因为在 javascript/typescript 中,如果您不想使用参数,则不会强制声明它们,只要不存在矛盾即可。
例如Array.forEach的签名是:
forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void;
但这会编译得很好:
let a = [1, 2, 3];
a.forEach(item => console.log(item));
这是一件好事,如果我必须拥有所有参数,即使我不使用它们,那也太可怕了。
这里也是如此:
type MyFn = (s: string) => void;
let fn: MyFn = () => console.log("hey");
如果我不需要使用字符串参数那么我可以忽略它,或者我什至可以这样做:
let fn: MyFn = () => console.log(arguments);
如果您将 Cat.getPlayBehavior
中 return 的函数签名更改为与 Animal
中的定义相矛盾的东西,那么您将得到一个错误:
class Cat extends Animal {
getPlayBehavior() {
return (n: number) => {
console.log(`Play with toy_var_would_go_here!`);
};
}
}
错误:
Class 'Cat' incorrectly extends base class 'Animal'.
Types of property 'getPlayBehavior' are incompatible.
Type '() => (n: number) => void' is not assignable to type '() => (toy: string) => void'.
Type '(n: number) => void' is not assignable to type '(toy: string) => void'.
Types of parameters 'n' and 'toy' are incompatible.
Type 'string' is not assignable to type 'number'.