如何根据传入的参数精确 `Promise` 返回的类型?

演示: https://tsplay.dev/NB6axN

代码:

const action = {
  '/posts': () => Promise.resolve(['a']),
  '/test': () => Promise.resolve([1]),
} as const;

type test = ReturnType<ActionType['/test']>;

async function getData<T extends ItemKey>(url: T) {
  return await action[url]();
}

type ActionType = typeof action;
type ItemKey = keyof typeof action;

const post = getData('/posts');   // Promise<string[]>
const test = getData('/test');   // Promise<number[]>

结果:

  • 传入 '/posts' 拿到 Promise<string[]>
  • 传入 '/test' 拿到 Promise<number[]>

前置条件:

  • 尽可能不要强行断言
阅读 967
3 个回答

尝试了一下

const action = {
  '/posts': () => Promise.resolve(['a']),
  '/test': () => Promise.resolve([1]),
} as const;

type test = ReturnType<ActionType['/test']>;

type ActionType = typeof action;
type ItemKey = keyof typeof action;
type DePromise<T> = T extends Promise<infer R> ? R : T;
type InferResult<T extends ItemKey> = DePromise<ReturnType<ActionType[T]>>;

async function getData<T extends ItemKey>(url: T): Promise<InferResult<T>> {
   return await action[url]() as InferResult<T>;
}


const post = getData('/posts');   // Promise<string[]>
const test = getData('/test');   // Promise<number[]>

传送门:http://u5a.cn/qcTA9

尝试的时候遇到些问题:

  1. async 函数的返回类型必须是 Promise<?>,没办法,只好先 DePromise 之后再把 Promise 加上。
  2. await action[url]() 自动推导出来的类型是 number[] | string[],所以只好用 as InferResult<T> 强制声明类型。
function getData<T extends ItemKey>(url: T) {
  return action[url]() as ReturnType<ActionType[T]>
}

为方法本身提供返回值类型不就可以了吗。

const action = {
  '/posts': (): Promise<string[]> => Promise.resolve(['a']),
}
const post = action['/posts']();
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
logo
Microsoft
子站问答
访问
宣传栏