繁体   English   中英

如何正确键入泛型函数的参数?

[英]How to correctly type Parameters of generic function?

我正在尝试将函数的参数分配给类型别名。 例如对于这个功能:

function foo<T>(bar: T, baz: number) {}

我想获得其参数的签名。 通常,我会这样做:

type FooParams = Parameters<typeof foo>;

但问题是这会导致[{}, number]的签名,这是有道理的,因为我没有指定T是什么。 但是,那么我希望这能奏效:

type FooParams<T> = Parameters<typeof foo<T>>; // hopefully [T, number]

但事实并非如此,它只会导致一堆语法错误。

是否可以正确获取泛型函数参数列表的类型?

您可以使用该infer关键字:

type Args<T> = T extends (...args: infer I) => any ? I : never;

type R = Args<(args: number, arg: string) => number >;
// R = [number, string] 

这意味着类型I被视为通用,但您不必像这样声明它: let fn = <T>(arg:T): T {...

游乐场, 文档


您可以实现泛型类型,但必须声明函数类型:

type Foo<T> = (bar: T, baz: number) => void;
type R2<Placeholder> = Args<Foo<Placeholder>>; // [Placeholder, number]
type R3 = R2<boolean> // [boolean, number]

我的解决方案只是一种可能有帮助的解决方法。 这不是你想要的

这里你有非通用的解决方案。我的意思是它只适用于foo类型签名

function foo<T>(bar: T, baz: number) { }

type Fn = (...args: any) => any
type Tail<T extends any[]> = T extends [infer _, ...infer Rest] ? Rest : never

type ReplaceFirstParameter<F extends Fn, Fst> =
    (fst: Fst, ...args: Tail<Parameters<F>>) => ReturnType<F>

type Foo<T> = ReplaceFirstParameter<typeof foo, T>

type Result = ReplaceFirstParameter<typeof foo, number> // (fst: number, baz: number) => void

这个解决方案是最通用的。 它将用提供的通用参数替换所有unknown参数。

我假设每个泛型函数都是未知的——这是弱点。

type MapPredicate<T, V> = T extends unknown ? V : T

type ReplaceUnknown<
    Arr extends Array<unknown>,
    Value,
    Result extends Array<unknown> = []
    > = Arr extends []
    ? []
    : Arr extends [infer H]
    ? [...Result, MapPredicate<H, Value>]
    : Arr extends [infer Head, ...infer Tail]
    ? ReplaceUnknown<[...Tail], Value, [...Result, MapPredicate<Head, Value>]>
    : Readonly<Result>;

function foo<T>(bar: T, baz: number) { }

type Fn = (...args: any) => any

type ReplaceParameters<F extends Fn, Value> =
    (...args: ReplaceUnknown<Parameters<F>, Value>) => ReturnType<F>


type Result = ReplaceParameters<typeof foo, number> // (fst: number, baz: number) => void

操场

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM