类型为 T 的函数的类型位于最后一个参数位置



我希望创建一个类型,表示那些在最后一个参数位置有类型T的函数。可变参数元组类型看起来可以毫无问题地解决这个问题,但在我目前的方法中,像这样的类型:

type TasLastArg<T> = (...args: [...any, T]) => any;

args论点是否崩溃为any[].其他地方也有类似的行为,让我认为这应该是可能的;目前不起作用的示例/为什么我认为这是可能的:

type TasFirstArg<T> = (...args: [T, ...any]) => any;  // this appears to work as expected
type TasLastArg<T> = (...args: [...any, T]) => any; // would like for this to work
namespace T_in_first_place {
const ok : TasFirstArg<string> = (x:string, y: number, z: string) => { return 0; }
const correctly_fails : TasFirstArg<string> = (x:number, y: number, z: number) => { return 0; }
}
namespace T_in_last_place {
const ok : TasLastArg<string> = (x:number, y: number, z: string) => { return 0; }
const should_fail_but_does_not: TasLastArg<string> = (x:number, y: number, z: number) => { return 0; }
}
// there is some machinery that allows looking at the last type in a tuple:
type CheckStringIsLast<T extends any[]> = T extends [...infer first, string] ? true : false;
type it_checks_this_fine = CheckStringIsLast<[number, number, string]>; // true
type it_properly_rejects_this = CheckStringIsLast<[number, number, number]>; // false

这是不可能的,还是我错过了什么?

TypeScript 4.1 仅支持元组类型末尾的 rest 元素。 可变参数元组类型允许您编写[...any, T],但这只会折叠为any[]

当 TypeScript 4.2 发布时,它应该在开头或中间开始接受 rest 元素(但每个元组只有一个 rest 元素)。 请参阅 microsoft/TypeScript#41544 了解实现此目的的 PR。 此时,[...any, T]将被解释为[...any[], T],意思是"任何末尾有T的元组",如您所愿。

请注意,一旦支持此功能,您的示例就不会真正达到您的预期:

const ok : TasLastArg<string> = (x:number, y: number, z: string) => { return 0; } // error!
// -> ~~
// Target requires 3 element(s) but source may have fewer

这是一个错误,因为虽然目标函数确实需要string作为其最后一个元素,但它不符合TasLastArg<string>,它需要是一个接受任何string结尾的参数列表的函数。 这意味着您需要能够这样称呼它:

ok("shouldWork");
ok(1, 2, 3, 4, 5, 6, 7, true, new Date(), "shouldAlsoWork");

对于(x: number, y: number, z: string) => number类型的函数来说,如果它的实现对xyz有任何有意义的作用,那将是灾难性的。 如果你想实现它,它需要一个本身以正确的方式是可变参数的函数:

const reallyOkay: TasLastArg<string> = (...args: [...initArgs: any[], lastArg: string]) => {
console.log((args[args.length - 1] as string).toUpperCase());
}
reallyOkay("shouldWork"); // SHOULDWORK
reallyOkay(1, 2, 3, 4, 5, 6, 7, true, new Date(), "shouldAlsoWork"); // SHOULDALSOWORK

不,至少在最初看来,args[args.length-1]不会被自动解释为string

操场链接到代码

相关内容

  • 没有找到相关文章

最新更新