![](/img/trans.png)
[英]How do I get typescript to infer the return type of a function based on the return type on a function of its arguments
[英]Is there any way to have TypeScript infer the type of a function's return value based on the call arguments?
我正在设置一个 function 将从我的数据库中检索数据。 它将键字符串作为参数,并根据键返回不同的数据类型。
我的目标是让 TypeScript 根据作为参数传递的键推断将返回的类型。
这是我尝试过的:
interface Fruits { names: string[] }
interface Employees { ages: number[] }
function getData(key: "fruits" | "employees") {
if (key === "fruits") {
// fetch data for /fruits and return it, specifying its type
return { names: ["apple", "orange", "kiwi"] } as Fruits;
}
// fetch data for /employees and return it, specifying its type
return { ages: [30, 50, 19 ] } as Employees;
}
const fruits = getData("fruits");
// ...should infer that the returned value will be of type 'Fruits'
const fruitNames = fruits.names;
// ...fails to infer type. Thinks fruits is of type (Fruits | Employees)
最后一行给出警告,因为 TypeScript 无法推断在调用 getData 时使用键“fruits”将始终返回 Fruits 类型的值(反过来,它具有属性“names”)。
当然,我也可以通过像这样对 getData 的调用进行类型转换来消除错误 go :
const fruits = getData("fruits") as Fruits;
但是,在我看来,这违背了首先使用 TypeScript 的目的,因为我的代码再次变得非常容易出错。 例如,如果我进行了错误的类型转换,技术上不正确的代码不会给出任何警告:
const fruits = getData("fruits") as Employees;
const nonexistent = fruits.ages;
// TS won't complain about any accesses to the non-existent property 'ages'
// because I made the wrong typecasting
我的目标是,使用 getData function 的人提前知道,多亏了 TypeScript 的 IntelliSense,一旦他们提供了用于查询数据的“密钥”字符串,他们就会立即返回数据类型。 调用 function 时,不必手动对函数的返回值类型进行类型转换。
在 getData 内部,任何类型转换、使用 generics 或任何其他类型都可以。 但是,除此之外,给 function 一个有效的键参数应该足以让 TypeScript 推断出正确的返回类型。
有什么办法可以做到这一点?
另一种方法是为每个具有适当类型的返回值的键声明function 重载。 您的实现将键入key
及其所有可能的值,并具有一个返回类型,该类型是所有可能返回的联合。 那看起来像:
interface Fruits { names: string[] }
interface Employees { ages: number[] }
function getData(key: "fruits"): Fruits;
function getData(key: "employees"): Employees;
function getData(key: "fruits" | "employees"): Fruits | Employees {
if (key === "fruits") {
// fetch data for /fruits and return it
return { names: ["apple", "orange", "kiwi"] };
}
// fetch data for /employees and return it
return { ages: [30, 50, 19 ] };
}
其实有好几种方法,这里有一种方法
interface Fruits {
names: string[];
}
interface Employees {
ages: number[];
}
interface DataMap {
fruits: Fruits;
employees: Employees;
}
function getData<T extends keyof DataMap>(key: T): DataMap[T] {
if (key === "fruits") {
// fetch data for /fruits and return it, specifying its type
return { names: ["apple", "orange", "kiwi"] } as DataMap[T];
}
// fetch data for /employees and return it, specifying its type
return { ages: [30, 50, 19] } as DataMap[T];
}
const fruits = getData("fruits"); // knows it's a Fruits
const fruitNames = fruits.names; // works
我们制作了一个辅助类型,用于将 map 字符串转换为类型,并使用此泛型来捕获 T 以便我们可以在返回类型中使用它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.