Geo*_*ids 1 extends types arguments typescript spread-syntax
标题几乎说明了一切。我有这个代码:
type testNoArgsF = () => number;
type testArgsF = (arg1: boolean, arg2: string) => number;
type unknownArgsF = (...args: unknown[]) => number;
type anyArgsF = (...args: any[]) => number;
type testII = testArgsF extends anyArgsF ? true : false; // true
type testIII = Parameters<testArgsF> extends Parameters<unknownArgsF>
? true
: false; // true
// unexpected:
type testIV = testArgsF extends unknownArgsF ? true : false; // false <- why?
// even though:
type testV = testNoArgsF extends unknownArgsF ? true : false; // true
Run Code Online (Sandbox Code Playgroud)
它是用打字稿(版本 3.8)编写的,并且我启用了严格模式。意想不到的结果是,测试函数不会扩展扩展参数为 的函数类型unknown[],但如果您只检查参数,它们就会扩展unknown[]。由于返回类型始终是数字,我不明白还有什么可能不同来伪造该extends语句。
其他注意事项:
--strictFunctionTypes启用编译器选项后,将对函数类型参数进行逆变检查。“逆变”是指函数的子类型关系与函数参数的子类型关系变化方向相反。因此A extends B,如果 ,则(x: B)=>void extends (x: A)=>void 反之亦然。
由于 TypeScript 中“可替代性”的本质(也称为行为子类型) ,这是一个类型安全问题。如果A extends B是 true,您应该能够将 an 用作Aa B。如果你不能,那就A extends B不是真的。
如果关闭--strict,则编译器将使用 TS-2.6 之前的双变量检查函数参数的行为,这是不安全的,但出于生产力的原因是允许的。这可能在这里偏离主题,但您可以在 TypeScript 常见问题解答条目“为什么函数参数是双变的?”中阅读更多相关信息。
无论如何,如果您需要一个接受任何数字unknown参数的函数类型,则不能安全地使用仅 的特定子类型的函数unknown。观察:
const t: testArgsF = (b, s) => (b ? s.trim() : s).length
const u: unknownArgsF = t; // error!
u(1, 2, 3); // explosion at runtime! s.trim is not a function
Run Code Online (Sandbox Code Playgroud)
如果testArgsF extends unknownArgsF为真,那么您将能够毫无错误地分配t给上面的内容,当愉快地接受非第二个参数时,立即导致运行时错误。 uustring
您可以看到,子类型/实现函数类型的唯一安全方法是子类型/实现接受与超类型/调用签名所期望的参数相同或更宽的参数。这就是--strictFunctionTypes引入该语言的原因。
如果您更改unknown为any(使用anyArgsF而不是unknownArgsF),那么编译器不会抱怨,因为在 TypeScript 中故意any不健全。该类型any被认为可以分配给所有其他类型,也可以从其他类型分配;这是不安全的,因为例如string extends any和any extends number都是 true 而string extends number是 false。any因此,当涉及到上述替代原则时,不强制执行。将值注释为any类型相当于放松或关闭对该值的类型检查。这并不能避免运行时错误;它只是消除编译器的错误:
const a: anyArgsF = t; // okay, type checking with any is disabled/loosened
a(1, 2, 3); // same explosion at runtime!
Run Code Online (Sandbox Code Playgroud)
在 为 true 的情况下testNoArgsF extends unknownArgsF,这也是可替代性的结果。您可以使用不带参数的函数,就好像它是任何函数类型一样,因为它(通常)最终会忽略传递给它的任何参数:
const n: testNoArgsF = () => 1;
const u2: unknownArgsF = n; // okay
u2(1, 2, 3); // okay at runtime, since `n` ignores its arguments
Run Code Online (Sandbox Code Playgroud)
TypeScript FAQ 条目“为什么参数较少的函数可以分配给参数较多的函数?”对此进行了解释。。
好的,希望有帮助;祝你好运!
| 归档时间: |
|
| 查看次数: |
1587 次 |
| 最近记录: |