打字稿:如何根据函数参数值缩小函数return类型

Typescript: How to narrow down function return type based on function parameter value

我对打字稿还很陌生,想不出一种方法来根据同一函数的参数正确缩小函数的 return 类型。

考虑以下代码:

import exampleApiResource from './resources/example';
import exampleApiResource2 from './resources/example2';
import { ApiResources } from './typings';

const apiResources: ApiResources = {
  exampleResource: exampleApiResource,
  exampleResource2: exampleApiResource2,
};

export function useApiClient(resource: keyof ApiResources) {
  return apiResources[resource];
}

export default apiResources;

/** typings **/
export type ApiResources = {
  exampleResource: ExampleType;
  exampleResource2: ExampleType2;
};

export type ExampleType = {
  getExample: () => Promise<TestResource>;
};

export type ExampleType2 = {
  getExample2: () => Promise<TestResource>;
};

我想通过 useApiClient 函数公开 apiResources 对象。 exampleApiResource 和 exampleApiResource2 拥有不同的属性,正如您在类型中看到的那样。

Typescript 将 useApiClient 函数推断为 return 以下类型:ExampleType | ExampleType2

如何将其缩小到特定类型,这可能吗?

--

用例:

通过函数公开基于 axios 的 API 客户端。该函数接受一个参数,该参数将解析为一个对象,该对象包含执行 API 相关操作的函数(例如:getPosts()、updatePost() 等)。

您应该将 useApiClient() 设为 generic function,其类型参数 K 对应于作为 resource 传入的 keyof ApiResources 的特定成员:

export function useApiClient<K extends keyof ApiResources>(resource: K) {
  return apiResources[resource];
}

现在函数的return类型是ApiResources[K],一个indexed access type对应于ApiResources处的属性值的类型K.

类型的键

当您根据输入调用 useApiClient() 和 return ExampleTypeExampleType2 时,您可以验证这是否会按预期运行:

const ex = useApiClient("exampleResource"); // const ex: ExampleType
const ex2 = useApiClient("exampleResource2"); // const ex2: ExampleType2

只有在输入类型也是联合的情况下,您才会得到联合 ExampleType | ExampleType2

const exUnion = useApiClient(
  Math.random() < 0.5 ? "exampleResource" : "exampleResource2"
);
// const exUnion: ExampleType | ExampleType2

Playground link to code