首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在TypeScript中推断函数参数

在TypeScript中推断函数参数
EN

Stack Overflow用户
提问于 2018-06-09 17:58:45
回答 2查看 9.6K关注 0票数 11

我正在尝试创建一个类型安全的map函数(不是下面的函数),但我坚持要获得函数参数才能正确推断。

代码语言:javascript
运行
复制
    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');

有没有可能让TypeScript来推断它们?目前,mapped对象内部的函数接受任何参数,但它应该只接受未映射对象中定义的参数。函数名可以正确推断出来。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-06-09 21:33:06

如果您使用(...args: any[]) => Promise<any>作为映射类型中的签名,您将丢失所有参数类型信息并返回类型信息。使用条件类型可以实现您想要做的事情的不完美的解决方案。here描述了这些限制。

该解决方案将需要创建一个条件类型,该类型使用给定数量的参数分别处理每个函数。下面的解决方案适用于最多10个参数(对于大多数实际情况来说已经足够了)

代码语言:javascript
运行
复制
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'); 
票数 6
EN

Stack Overflow用户

发布于 2019-03-08 09:55:53

可以使用ParametersReturnType泛型来获取函数的具体参数和返回类型:

代码语言:javascript
运行
复制
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]>
}
票数 23
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50773038

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档