hou*_*fio 7 typescript typescript-typings
我正在尝试制作一个类型安全的映射函数(而不是下面的函数),但是我一直坚持获取要正确推断的函数参数。
export type Mapper<U extends Unmapped> = {
mapped: Mapped<U>
};
export type Unmapped = {
[name: string]: (...args: any[]) => any
};
export type Mapped<U extends Unmapped> = {
[N in keyof U]: (...args: any[]) => Promise<any>
};
const map = <U extends Unmapped>(unmapped: U): Mapper<U> => ({
mapped: Object.entries(unmapped).reduce(
(previous, [key, value]) => ({
...previous,
[key]: (...args: any[]) => new Promise((resolve) => resolve(value(...args)))
}),
{}
) as Mapped<U>
});
const mapped = map({ test: (test: number) => test });
mapped.mapped.test('oh no');
Run Code Online (Sandbox Code Playgroud)
是否可以让TypeScript推断它们?当前,mapped对象内部的函数可以接受任何参数,但是只能接受未映射对象中定义的参数。函数名称确实可以正确推断。
如果您(...args: any[]) => Promise<any>在映射类型中用作签名,您将丢失所有参数类型信息并返回类型信息。使用条件类型可以实现对您想要做的事情的不完美解决方案。此处描述了这些限制。
该解决方案需要创建一个条件类型,分别处理具有给定数量参数的每个函数。下面的解决方案最多适用于 10 个参数(对于大多数实际情况来说已经足够了)
export type Mapper<U extends Unmapped> = {
mapped: Mapped<U>
};
export type Unmapped = {
[name: string]: (...args: any[]) => any
};
type IsValidArg<T> = T extends object ? keyof T extends never ? false : true : true;
type Promisified<T extends Function> =
T extends (...args: any[]) => Promise<any> ? T : (
T extends (a: infer A, b: infer B, c: infer C, d: infer D, e: infer E, f: infer F, g: infer G, h: infer H, i: infer I, j: infer J) => infer R ? (
IsValidArg<J> extends true ? (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J) => Promise<R> :
IsValidArg<I> extends true ? (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I) => Promise<R> :
IsValidArg<H> extends true ? (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H) => Promise<R> :
IsValidArg<G> extends true ? (a: A, b: B, c: C, d: D, e: E, f: F, g: G) => Promise<R> :
IsValidArg<F> extends true ? (a: A, b: B, c: C, d: D, e: E, f: F) => Promise<R> :
IsValidArg<E> extends true ? (a: A, b: B, c: C, d: D, e: E) => Promise<R> :
IsValidArg<D> extends true ? (a: A, b: B, c: C, d: D) => Promise<R> :
IsValidArg<C> extends true ? (a: A, b: B, c: C) => Promise<R> :
IsValidArg<B> extends true ? (a: A, b: B) => Promise<R> :
IsValidArg<A> extends true ? (a: A) => Promise<R> :
() => Promise<R>
) : never
);
export type Mapped<U extends Unmapped> = {
[N in keyof U]: Promisified<U[N]>
}
const map = <U extends Unmapped>(unmapped: U): Mapper<U> => ({
mapped: Object.entries(unmapped).reduce(
(previous, [key, value]) => ({
...previous,
[key]: (...args: any[]) => new Promise((resolve) => resolve(value(...args)))
}),
{}
) as Mapped<U>
});
const mapped = map({ test: (test: number) => test });
mapped.mapped.test('oh no');
Run Code Online (Sandbox Code Playgroud)
可以使用Parameters和ReturnType泛型类型来获取函数的特定参数和返回类型:
type Promisified<T extends (...args: any[]) => any> = (...args: Parameters<T>) => Promise<ReturnType<T>>;
export type Mapped<U extends Unmapped> = {
[N in keyof U]: Promisified<U[N]>
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2517 次 |
| 最近记录: |