简体   繁体   English

有没有办法让 TypeScript 根据调用 arguments 推断函数返回值的类型?

[英]Is there any way to have TypeScript infer the type of a function's return value based on the call arguments?

I'm setting up a function that will retrieve data from my database.我正在设置一个 function 将从我的数据库中检索数据。 It takes a key string as argument, and it returns a different data type based on the key.它将键字符串作为参数,并根据键返回不同的数据类型。

My goal is to have TypeScript infer the type that will be returned based on the key that's passed as argument.我的目标是让 TypeScript 根据作为参数传递的键推断将返回的类型。

This is what I've tried:这是我尝试过的:

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)

The last line gives a warning because TypeScript could not infer that using the key "fruits" when calling getData will always return a value of type Fruits (which, in turn, has the property "names").最后一行给出警告,因为 TypeScript 无法推断在调用 getData 时使用键“fruits”将始终返回 Fruits 类型的值(反过来,它具有属性“names”)。

Of course, I could make the error go away by also typecasting my call to getData like this:当然,我也可以通过像这样对 getData 的调用进行类型转换来消除错误 go :

const fruits = getData("fruits") as Fruits;

But, in my opinion, that defeats the purpose of using TypeScript in the first place since once again my code becomes very error-prone.但是,在我看来,这违背了首先使用 TypeScript 的目的,因为我的代码再次变得非常容易出错。 If, for example, I make the wrong typecasting, code that's technically incorrect won't give any warning:例如,如果我进行了错误的类型转换,技术上不正确的代码不会给出任何警告:

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

My goal is that whoever uses the getData function knows, in advance, thanks to TypeScript's IntelliSense, the type of data they will get back as soon as they provide the 'key' string to query data with.我的目标是,使用 getData function 的人提前知道,多亏了 TypeScript 的 IntelliSense,一旦他们提供了用于查询数据的“密钥”字符串,他们就会立即返回数据类型。 It should not be necessary to manually typecast the function's return value type when calling the function.调用 function 时,不必手动对函数的返回值类型进行类型转换。

Inside of getData, any typecasting, use of generics, or any other typing is fine.在 getData 内部,任何类型转换、使用 generics 或任何其他类型都可以。 But, outside of it, giving the function a valid key argument should be enough to have TypeScript infer the correct return type.但是,除此之外,给 function 一个有效的键参数应该足以让 TypeScript 推断出正确的返回类型。

Is there any way to achieve this?有什么办法可以做到这一点?

Another approach is to declare a function overload for each of the keys with a return value of the appropriate type.另一种方法是为每个具有适当类型的返回值的键声明function 重载 Your implementation would type key with all its possible values and have a return type that is a union of all the possible returns.您的实现将键入key及其所有可能的值,并具有一个返回类型,该类型是所有可能返回的联合。 That would look like:那看起来像:

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 ] };
}

There is actually several ways, here is one way其实有好几种方法,这里有一种方法

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

We make an auxilliary type which serves to map strings to types, and use this generic to capture T so we can use it in the return type.我们制作了一个辅助类型,用于将 map 字符串转换为类型,并使用此泛型来捕获 T 以便我们可以在返回类型中使用它。

暂无
暂无

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

相关问题 我如何让 typescript 根据 function2E977777777777777777777777777777777777777777777777777777777777777777777777777777777777BED18 的返回类型 functionC17A94F14Z 的返回类型来推断 function 的返回类型 - 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 a way for typescript to infer arguments object or have a type defined for arguments object? 根据 TypeScript 中可区分联合的参数自动推断返回类型 - Automatically infer return type based on arguments for discriminated union in TypeScript TypeScript - 根据来自另一个 function 的返回类型推断函数的参数类型 - TypeScript - infer function's argument type based on return type from another function 打字稿:正确推断包装函数的参数和返回类型 - Typescript: correctly infer arguments and return type for wrapped function 如何根据函数参数推断 Promise 的返回类型? - How to infer return type of Promise based on function arguments? 根据泛型值推断 Typescript class 返回泛型类型 - Infer Typescript class to return the generic type based of generic value 在TypeScript中,如何键入函数的参数而不是返回值? - In TypeScript, how do i type a function's arguments but not the return value? TypeScript:是否可以根据 function 调用是否成功来推断类型? - TypeScript: is it possible to infer a type based on whether a function call succeeds? TypeScript 从使用的参数推断返回类型 - TypeScript infer return type from used arguments
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM