[英]Typescript: How can I get return type of function based on argument type?
I want return type to be based on "config" argument我希望返回类型基于“config”参数
now return type of exampleFn function is empty {}现在返回 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"
is it possible?可能吗?
The compiler won't be smart enough to figure this out on its own, but you can certainly describe the type you want and use type assertions inside the implementation of exampleFn()
to prevent it from complaining... keeping in mind that such type assertions shift the burden of type safety from the compiler to you.编译器不会聪明到自己解决这个问题,但你当然可以描述你想要的类型并在
exampleFn()
的实现中使用类型断言来防止它抱怨......记住这样的类型断言将类型安全的负担从编译器转移到您身上。
Here's the type I think you want:这是我认为你想要的类型:
{ [K in Extract<keyof T, keyof Interface>]: typeof DEFAULT_VALUES[K] }
Basically you are making a mapped type where the keys are the keys from T
which are also present in Interface
(it is possible for T
to contain more keys because T extends Partial<Interface>
allows such extension; if you really want to prohibit this you can, but for now I'm going to leave this as you have it), and the values are the corresponding types from the DEFAULT_VALUES
value.基本上你正在制作一个映射类型,其中键是来自
T
的键,它们也存在于Interface
中( T
可能包含更多键,因为T extends Partial<Interface>
允许这样的扩展;如果你真的想禁止这个,你可以,但是现在我将保留它),并且值是来自DEFAULT_VALUES
值的相应类型。
Here's the implementation:这是实现:
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] };
};
You can see that I am asserting that key
is keyof Interface
(since key
is only known to be string
by the compiler) and that map
is the desired return type.您可以看到我断言
key
是keyof Interface
(因为编译器只知道key
是string
)并且map
是所需的返回类型。 Let's see how it works:让我们看看它是如何工作的:
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
Looks good to me.在我看来很好。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.