Typescript从函数返回中提取类型 (By Gemini 2.5 Pro)

可以使用 TypeScript 的 ReturnType条件类型 (Conditional Types) 配合 infer 关键字来从函数的返回类型中提取 Promise 内的数据类型,而无需显式定义 data 的类型。


方法

假设你的函数是这样的:

function fetchData() {
  return Promise.resolve({ name: 'Alice', age: 30 }); // 这里的 { name: 'Alice', age: 30 } 就是未显式定义的 data
}

你可以通过以下步骤来获取 data 的类型:

  1. 获取函数的返回类型: 使用 ReturnType<typeof fetchData> 来获取 fetchData 函数的返回类型,在这个例子中是 Promise<{ name: string; age: number; }>
  2. 提取 Promise 内的类型: 定义一个条件类型来提取 Promise 包裹的类型。

下面是具体的实现:

// 1. 你的异步函数
async function fetchData() {
  // 假设这里有一些异步操作
  return {
    id: 1,
    title: 'TypeScript Rocks!',
    completed: false,
    details: {
      author: 'Unknown',
      tags: ['typescript', 'promise', 'utility-types']
    }
  };
}

// 2. 使用 ReturnType 获取函数 fetchData 的返回类型 (即 Promise<data>)
type FetchDataReturnType = ReturnType<typeof fetchData>;
// FetchDataReturnType 的类型是: Promise<{ id: number; title: string; completed: boolean; details: { author: string; tags: string[]; }; }>

// 3. 定义一个工具类型来提取 Promise 中的泛型类型
type UnpackPromise<T> = T extends Promise<infer U> ? U : T;

// 4. 使用 UnpackPromise 工具类型来获取 data 的实际类型
type DataType = UnpackPromise<FetchDataReturnType>;
// DataType 的类型现在是: { id: number; title: string; completed: boolean; details: { author: string; tags: string[]; }; }

// 现在你可以使用 DataType 了
const myData: DataType = { // TypeScript 会进行类型检查
  id: 2,
  title: 'Another Post',
  completed: true,
  details: {
    author: 'Jane Doe',
    tags: ['example']
  }
};

console.log(myData);

// 如果你尝试给 myData 赋一个不符合推断出来的类型的对象,TypeScript 会报错:
// const wrongData: DataType = {
//   name: 'Test' // Error: Property 'id' is missing in type '{ name: string; }' but required in type '{ id: number; title: string; completed: boolean; details: { author: string; tags: string[]; }; }'.
// };

解析

  • typeof fetchData: 获取 fetchData 函数的类型。
  • ReturnType<Type>: 这是一个 TypeScript 内置的工具类型,它会获取函数类型 Type 的返回类型。
  • type UnpackPromise<T> = T extends Promise<infer U> ? U : T;:
    • 这是一个条件类型。
    • T extends Promise<infer U>: 判断类型 T 是否可以赋值给 Promise<infer U>
      • infer U: 这是关键。如果 T 的确是一个 Promise,TypeScript 会尝试推断 Promise 的泛型参数 U 的类型,并将这个推断出来的类型赋给 U
    • ? U: 如果条件为真(即 T 是一个 Promise),则 UnpackPromise<T> 的类型就是推断出来的 U(也就是 Promise 内部 data 的类型)。
    • : T: 如果条件为假(即 T 不是一个 Promise),则 UnpackPromise<T> 的类型就是 T 本身(这个回退逻辑可以根据你的具体需求调整,比如返回 never)。

通过这种方式,你就不需要预先定义 data 的接口或类型,TypeScript 会自动从你的函数实现中推断出它的结构。这在处理一些动态返回或者你不想显式维护返回类型的场景下非常有用。

posted @ 2025-06-01 11:16  Cmen  阅读(54)  评论(0)    收藏  举报