【问题标题】:Typescript: How can I get return type of function based on argument type?Typescript:如何根据参数类型获取函数的返回类型?
【发布时间】:2021-01-11 06:09:06
【问题描述】:

我希望返回类型基于“config”参数

现在 exampleFn 函数的返回类型为空 {}

interface Interface {
    a: number;
    b: string;
}
const DEFAULT_VALUES = {
    a: (num: number) => 1 + num,
    b: (str: string) => 'a' + str,
}
const exampleFn = <T extends Partial<Interface>>(config: T) => {
    const map = {};

    Object.entries(config).forEach(([key, val]) => {
        map[key] = DEFAULT_VALUES[key];
    });
    
    return map;
};

const example1 = exampleFn({ a: 123 }); // I want example1 return type to be "{a: (num: number) => number}"
const example2 = exampleFn({ b: 'asd' }); // I want example2 return type to be "{b: (str: string) => string}"
const example3 = exampleFn({ a: 123, b: 'asd' }); // I want example3 return type to be "{a: (num: number) => number, b: (str: string)} => string"

有可能吗?

【问题讨论】:

    标签: typescript typescript-typings typescript-generics


    【解决方案1】:

    编译器不会聪明到自己解决这个问题,但你当然可以描述你想要的类型并在exampleFn()的实现中使用type assertions来防止它抱怨......保持请注意,此类类型断言将类型安全的负担从编译器转移到您身上。

    这是我认为你想要的类型:

    { [K in Extract<keyof T, keyof Interface>]: typeof DEFAULT_VALUES[K] }
    

    基本上你正在创建一个mapped type,其中键是来自T 的键,它们也存在于Interface 中(T 可能包含更多键,因为T extends Partial&lt;Interface&gt; 允许这样的扩展;如果你真的想禁止这个你可以,但现在我将保留它),并且值是来自 DEFAULT_VALUES 值的相应类型。

    下面是实现:

    const exampleFn = <T extends Partial<Interface>>(config: T) => {
       const map = {} as any;
    
       Object.entries(config).forEach(([key, val]) => {
          map[key] = DEFAULT_VALUES[key as keyof Interface];
       });
    
       return map as { [K in Extract<keyof T, keyof Interface>]: typeof DEFAULT_VALUES[K] };
    };
    

    您可以看到我断言keykeyof Interface(因为编译器只知道keystring)并且map 是所需的返回类型。让我们看看它是如何工作的:

    const example1 = exampleFn({ a: 123 });
    console.log(example1.a(123)); // 124
    console.log(example1.b); // undefined
    // error!  --------> ~
    // Property 'b' does not exist on type '{ a: (num: number) => number; }'
    const example2 = exampleFn({ b: 'asd' });
    console.log(example2.b("asd")); // aasd
    const example3 = exampleFn({ a: 123, b: 'asd' });
    console.log(example3.b("asd")); // aasd
    console.log(example3.a(123)); // 124
    

    我觉得不错。

    Playground link to code

    【讨论】:

      猜你喜欢
      • 2021-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-13
      • 1970-01-01
      • 1970-01-01
      • 2021-05-13
      • 2020-04-27
      相关资源
      最近更新 更多