繁体   English   中英

Typescript:如何根据参数类型获取 function 的返回类型?

[英]Typescript: How can I get return type of function based on argument type?

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

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

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"

可能吗?

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

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

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

基本上你正在制作一个映射类型,其中键是来自T的键,它们也存在于Interface中( T可能包含更多键,因为T extends Partial<Interface>允许这样的扩展;如果你真的想禁止这个,你可以,但是现在我将保留它),并且值是来自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 代码链接

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM