Phi*_*ley 2 typescript typescript-generics
将泛型参数指定为函数是否...args: unknown[]效果不佳?
// Using TS 4.2.3
const fn = (foo: boolean) => 'hello'
// Ideally, one generic function arg
type Data1<M extends (...args: unknown[]) => unknown> = {
fn: M
}
const data1: Data1<typeof fn> = {
^^^^^^^^^
fn,
}
Run Code Online (Sandbox Code Playgroud)
Type '(foo: boolean) => string' does not satisfy the constraint '(...args: unknown[]) => unknown'.
Types of parameters 'foo' and 'args' are incompatible.
Type 'unknown' is not assignable to type 'boolean'.
Run Code Online (Sandbox Code Playgroud)
这个TypeScript Playground示例还演示了将函数拆分为两个通用参数,这可以工作,但从 API 的角度来看并不好。我希望更好地理解为什么一个有效,但另一个无效。
这是由于差异而发生的而发生的。
\ndeclare function fn(foo: boolean): string\n\ntype Data1<M extends (...args: unknown[]) => unknown> = {\n fn: M\n}\n\nconst data1: Data1<typeof fn> = {\n ^\n// Type \'(foo: boolean) => string\' does not satisfy the constraint \'(...args: unknown[]) => unknown\'.\n// Types of parameters \'foo\' and \'args\' are incompatible.\n// Type \'unknown\' is not assignable to type \'boolean\'.\n fn,\n}\nRun Code Online (Sandbox Code Playgroud)\n接受函数类型的数据类型Data1在该函数的结果类型中是协变的,在函数的参数类型中是逆变的。将其 ( Data1) 想象为一个接受参数的函数(它在类型级别上的真正含义)(foo: boolean) => string。该函数必须检查该参数是否可“分配”给参数的类型(...args: unknown[]) => unknown。要检查此检查器必须确保两件事:
函数的返回类型string必须可分配给unknown. 这是完全有可能的。所有类型均可分配给unknown.
参数的参数类型unknown[]必须可分配给函数的参数类型 [ boolean]。这就是检查器引发错误的地方。因为unknown只能分配给unknown和any。
为什么当涉及到争论时它必须发生在相反的方向?因为作为参数传递的函数是数据的使用者。它必须处理比预期作为参数的函数更广泛的类型。简单的例子:
\nfunction lowerCase(s: string): string {\n return s.toLowerCase()\n}\n\nfunction callCb(cb: (sn: string | number) => string | number): number {\n const stringOrNumber = cb(Math.random() ? \'string\' : 10)\n\n return typeof stringOrNumber === \'string\' \n ? stringOrNumber.length \n : stringOrNumber \xe2\x80\x8b\n} \n\ncallCb(lowerCase)\nRun Code Online (Sandbox Code Playgroud)\nTS 游乐场strictFunctionTypes关闭以说明不健全。
虽然可以返回预期参数返回类型(字符串、数字、字符串|数字)cb的任何子集,但必须能够处理每种类型callCbcbcallCb可以提供给它的
type Data2<Args extends unknown [], Return extends unknown> = {\n \xe2\x80\x8bfn: (...args: Args) => Return\n}\n\nconst data2: Data2<Parameters<typeof fn>, ReturnType<typeof fn>> = {\n \xe2\x80\x8bfn,\n}\nRun Code Online (Sandbox Code Playgroud)\n至于你的Data2类型。您为其提供了准确的fn您在协变/正位置首先它检查提供的类型是否满足约束:
\xe2\x80\x8b* 第一个类型参数[boolean]可分配给unknown[]\n\xe2\x80\x8b* 第二个类型参数string可分配给unknown
然后它检查您在 type 赋值右侧传递的对象是否{ fn: (foo: boolean) => string }可分配给Data2result type { fn: (...[boolean]) => string }。显然是这样。
strictFunctionTypes您可以通过禁用中的选项来关闭此行为tsconfig.json。然后打字稿将函数参数视为双变量。尽管我强烈建议不要这样做。\n\xe2\x80\x8b
| 归档时间: |
|
| 查看次数: |
3004 次 |
| 最近记录: |