Typescript:获取函数类型的最后一个参数的类型

时间:2019-05-29 21:26:30

标签: typescript

假设我有一个函数类型,例如

Exception in thread "main" java.lang.Error: Unresolved compilation problems: 
    Duplicate local variable dmx_output
    Duplicate local variable dmx_output
    Duplicate local variable dmx_output
    Duplicate local variable dmx_output
    Duplicate local variable dmx_output
    Duplicate local variable dmx_output
    Duplicate local variable dmx_output
    Duplicate local variable dmx_output
    Duplicate local variable dmx_output
    Duplicate local variable dmx_output
    Duplicate local variable dmx_output
    Duplicate local variable dmx_output
    Duplicate local variable dmx_output
    Duplicate local variable dmx_output
    Duplicate local variable dmx_output
    Duplicate local variable dmx_output
    Duplicate local variable dmx_output
    Duplicate local variable dmx_output
    Duplicate local variable dmx_output
    Duplicate local variable dmx_output
    Duplicate local variable dmx_output
    Duplicate local variable dmx_output
    Duplicate local variable dmx_output
    Duplicate local variable dmx_output
    Duplicate local variable dmx_output
    Duplicate local variable dmx_output
    dmx_output cannot be resolved
    dmx_output cannot be resolved

    at test.main(test.java:59)

我需要该函数的类型是最后一个参数:

type somefntype = (a: number, b: string, c: boolean) => void

如何定义type lastparamtype = LastParameter<somefntype> // lastparamtype == boolean

4 个答案:

答案 0 :(得分:1)

TypeScript 3.0引入了tuple types in rest and spread expressions,专门用于在功能参数列表和tuples的类型之间进行编程转换。有一个名为Parameters<F> defined in the standard library的类型别名,它以元组的形式返回函数的参数列表。

这很烦人,但有可能获得具有固定但任意长度的元组类型的最后一个元素:

// Tail<T> returns a tuple with the first element removed
// so Tail<[1, 2, 3]> is [2, 3]
// (works by using rest tuples)
type Tail<T extends any[]> = 
  ((...t: T)=>void) extends ((h: any, ...r: infer R)=>void) ? R : never;

// Last<T> returns the last element of the tuple
// (works by finding the one property key in T which is not in Tail<T>)
type Last<T extends any[]> = T[Exclude<keyof T, keyof Tail<T>>];

将它们组合在一起

type LastParameter<F extends (...args: any)=>any> = Last<Parameters<F>>;

我们可以对其进行测试:

type somefntype = (a: number, b: string, c: boolean) => void
type lastparamtype = LastParameter<somefntype> // boolean

对我很好。 Link to code

希望有所帮助;祝你好运!

答案 1 :(得分:1)

从带有可变元组支持的TypeScript 4.0开始,也可以使用以下命令获取元组类型中的最后一个类型:

type LastType<T extends [unknown, ...Array<unknown>]> = T extends [...infer A, infer L] ? L : never;

答案 2 :(得分:0)

对于具有3个args解决方案的函数,将是

type somefntype = (a: number, b: string, ddd: boolean) => void
type LastParameter<T> = T extends (a: infer A1, b: infer A2, c: infer A3) => any ? A3 : never;

type lastArg = LastParameter<somefntype>;  // === boolean

函数名称的名称不一致。

对于具有任意数量参数的函数,任务变得有点复杂。我们可以使用...rest,但它将是数组。

type LastParameter<T> = T extends (...rest: infer A3) => any ?
    A3 : never;
type lastArg = LastParameter<somefntype>; // lastArg === [number, string, boolean]

获取结果元组的最后一个元素有点挑战。 article启发了一种可能的解决方案。

type Prev<T extends number> = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62][T];
type GetLength<original extends any[]> = original extends { length: infer L } ? L : never;
type GetLast<original extends any[]> = original[Prev<GetLength<original>>]

type somefntype = (a: number, b: string, ddd: boolean) => void
type LastParameter1<T> = T extends (...rest: infer A3) => any ?
    A3 extends any[] ? GetLast<A3> : never
    : never;
type lastArg = LastParameter<somefntype>; // boolean for 3 arg function

第二种解决方案对函数的参数数量有所限制。

答案 3 :(得分:0)

这是另一种解决方案,它对jcalz答案做了些微修改,以使用某些递归条件类型使其更加通用:

type Head<T extends any[]> = T extends [any, ...any[]] ? T[0] : never;
type Tail<T extends any[]> =
    ((...t: T) => any) extends ((_: any, ...tail: infer U) => any)
        ? U
        : [];
type HasTail<T extends any[]> = T extends ([] | [any]) ? false : true;

type Last<T extends any[]> = {
    0: Last<Tail<T>>
    1: Head<T>
}[
    HasTail<T> extends true ? 0 : 1
];

type LastType = Last<Parameters<somefntype>>; // boolean

考虑将any也替换为unknown可能很有趣。