Ali*_*ian 3 typescript typescript-generics typescript-typings
我试图定义一个类型,它获取一个函数类型作为泛型参数,并返回一个与输入函数类型相同的函数类型,只是它最后多了一个参数:
type AugmentParam<F extends (...args: any[]) => any, ExtraParam> = F extends (
...args: infer Args
) => infer R
? (
...args: [
...Args,
ExtraParam
]
) => R
: never
Run Code Online (Sandbox Code Playgroud)
用法示例:
type F = (x: number) => boolean
type F2 = AugmentParam<F, string> // (x: number, arg2: string) => boolean
Run Code Online (Sandbox Code Playgroud)
...Args 似乎不起作用,但是如果我将其更改为这样的内容,它会起作用:
type F = (x: number) => boolean
type F2 = AugmentParam<F, string> // (x: number, arg2: string) => boolean
Run Code Online (Sandbox Code Playgroud)
但它只适用于特定数量的参数,我需要为每个 n 元函数定义一个这样的类型。
TypeScript 可以很容易地表示将类型添加到元组类型上,Cons<H, T>如下所示:
type Cons<H, T extends readonly any[]> =
((h: H, ...t: T) => void) extends ((...r: infer R) => void) ? R : never
type ConsTest = Cons<1, [2, 3, 4]>;
// type ConsTest = [1, 2, 3, 4]
Run Code Online (Sandbox Code Playgroud)
您可以使用此定义使用条件映射的元组类型一起产生Push<T, V>,以追加一个类型到一个元组的结尾:
type Push<T extends readonly any[], V> = Cons<any, T> extends infer A ?
{ [K in keyof A]: K extends keyof T ? T[K] : V } : never
type PushTest = Push<[1, 2, 3], 4>;
// type PushTest = [1, 2, 3, 4]
Run Code Online (Sandbox Code Playgroud)
但这个定义Push是脆弱的。如果T元组具有可选元素,或者它来自函数的参数列表,您会注意到编译器将可选标记和参数名称向右“移动”一个元素:
type Hmm = (...args: Push<Parameters<(optStrParam?: string) => void>, number>) => void;
// type Hmm = (h: string | undefined, optStrParam?: number) => void
Run Code Online (Sandbox Code Playgroud)
参数名称实际上并不是类型的一部分,因此虽然很烦人,但它不会影响实际类型。在可选参数之后附加一个参数是......很奇怪,所以我不确定那里的正确行为是什么。不确定这些是否适合您,但请注意。
无论如何,你AugmentParam看起来像:
type AugmentParam<F extends (...args: any[]) => any, ExtraParam> =
(...args: Extract<Push<Parameters<F>, ExtraParam>, readonly any[]>)
=> ReturnType<F>
Run Code Online (Sandbox Code Playgroud)
并且它有效(带有早期的警告):
type F = (x: number) => boolean
type F2 = AugmentParam<F, string>
// type F2 = (h: number, x: string) => boolean
type F3 = AugmentParam<F2, boolean>
// type F3 = (h: number, h: string, x: boolean) => boolean
Run Code Online (Sandbox Code Playgroud)
好的,希望有帮助。祝你好运!
| 归档时间: |
|
| 查看次数: |
4943 次 |
| 最近记录: |