gpt4 book ai didi

javascript - TypeScript:在 Promise 中包装函数参数

转载 作者:行者123 更新时间:2023-12-05 00:37:56 25 4
gpt4 key购买 nike

我尝试创建一个采用函数类型的类型,将函数参数包装在 Promise<> 中并返回一个新类型 - 相同的函数,但参数与 Promise 相同,例如:

type PromisedFn = PromisedArgs<(a: number, b: string | number) => void>
// should produce (a: Promise<number>, b: Promise<string | number>) => void
经过几个小时的绞尽脑汁,我只设法实现了这样的代码:
type Func = (id: number, guid: number | string) => number | string; 
type FuncParams = Parameters<Func>;
// FuncParams = [id: string, guid: string | number]

type FuncWrappedParams = {
[K in keyof FuncParams as Extract<K, '0'|'1'>]: Promise<FuncParams[K]>
}
// { 0: Promise<number>, 1: Promise<string | number> }
仍然无法将数字索引对象作为数组正确应用:
type FuncWrappedParamsArray = [...args: FuncWrappedParams[]];
type WrappedParamsFunc = (...args: FuncWrappedParamsArray) => ReturnType<Func>;

let func: WrappedParamsFunc = (
id: Promise<number>,
guid: Promise<number | string>
) => 'TestString';

// ERROR:
// Type '(id: Promise<number>, guid: Promise<number | string>) => string'
// is not assignable to type 'WrappedParamsFunc'.
// Types of parameters 'id' and 'args' are incompatible.
// Type 'FuncWrappedParams' is missing the following properties from type 'Promise<number>':
// then, catch, [Symbol.toStringTag]
我不知道如何处理这个。
问题 #1 如上所述。
问题#2:缺点是我们必须提前知道一些函数参数: [K in keyof FuncParams as Extract<K, '0'|'1'>] .

最佳答案

你可以写PromisedArgs像这样:

type PromisedArgs<T extends (...args: any) => any> =
T extends (...args: infer A) => infer R ? (
(...args: { [I in keyof A]: Promise<A[I]> }) => R
) : never;
只要您的数组类型是 generic类型参数(如上面的 A),一个 mapped type over it will produce another array type .在 {[I in keyof A]: ...} , key 类型 I本质上只是自动迭代类似数字的索引。您不必手动抓取 "0" | "1" | "2" | ...或者担心如何将生成的映射类型提升回数组。
使用 the infer keyword in the conditional type check只是一次获取函数的参数和返回类型的一种方法,而不是使用 the Parameters<T> the ReturnType utility types分别地。如果您查看定义 of Parameters of ReturnType 您会看到它们的实现方式相同。
无论如何,让我们确保它按预期工作:
type Func = (id: number, guid: number | string) => number | string;
type WrappedParamsFunc = PromisedArgs<Func>
/* type WrappedParamsFunc =
(id: Promise<number>, guid: Promise<string | number>) => string | number */

let func: WrappedParamsFunc = (
id: Promise<number>,
guid: Promise<number | string>
) => 'TestString';
看起来不错!

顺便说一句,TypeScript 中有一个错误,报告于 microsoft/TypeScript#27995 ,这可能会阻止您自己找到此解决方案。事实证明,您要映射到类似数组的泛型类型参数的键上,这一点很重要。如果您尝试映射特定类型,则映射将回退到迭代所有键,甚至是数组方法和东西:
type Foo = [1, 2, 3]
type Bar = { [I in keyof Foo]: Promise<Foo[I]> };
/* type Bar = {
[x: number]: Promise<3 | 1 | 2>;
0: Promise<1>;
1: Promise<2>;
2: Promise<3>;
length: Promise<3>;
toString: Promise<() => string>;
...
*/
由于 Foo是特定类型而不是类型参数,您会得到上面的困惑。您的 FuncParams是特定类型,如 Foo ,并且您尝试手动清理困惑,但效果不佳。那好吧!
Playground link to code

关于javascript - TypeScript:在 Promise<T> 中包装函数参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71500678/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com