TypeScript中Unpacked<T>的实用场景:已有ResponseData为何仍需它?
先看你给出的示例代码:
定义ResponseData接口与getData函数
interface ResponseData { data: string[]; hasMoreItems: boolean; } const getData = (): Promise<ResponseData> => { const data = { data: ['one', 'two', 'three', 'four'], hasMoreItems: false } return Promise.resolve(data); }
Unpacked类型定义与示例
type Unpacked<T> = T extends (infer U)[] ? U : T extends (...args: any[]) => infer U ? U : T extends Promise<infer U> ? U : T; type PromiseResult = Unpacked<ReturnType<typeof getData>>; // PromiseResult = ResponseData type FunctionResult = Unpacked<() => string>; // FunctionResult = string
Unpacked的实用价值
处理第三方/未知类型场景:如果调用第三方库的函数,你可能不想手动查文档定义返回值接口,或者根本不知道Promise包裹的具体类型。用Unpacked可以直接提取出Promise内部的类型,不用重复造轮子。比如第三方库有个
fetchUser()返回Promise<User>,你不用先定义User,直接用Unpacked<ReturnType<typeof fetchUser>>就能拿到User类型。泛型工具的复用性:写通用工具函数时,Unpacked能统一处理多种嵌套类型。比如写一个通用异步处理函数,需要把Promise的返回值类型作为回调参数类型,Unpacked就能帮你自动推导:
function handleAsync<T extends () => Promise<any>>(fn: T, callback: (result: Unpacked<ReturnType<T>>) => void) { fn().then(callback); } handleAsync(getData, (res) => { // res自动推断为ResponseData类型 console.log(res.data); });统一多种类型的拆包逻辑:Unpacked不止能处理Promise,还能提取数组的元素类型、函数的返回值类型。比如
Unpacked<string[]>能拿到string,Unpacked<() => number>能拿到number,相当于把数组、函数、Promise这几种常见的“包装类型”的拆包逻辑整合到一个工具类型里,不用单独写多个类型工具。减少类型重复定义:如果项目里有大量返回Promise的函数,每个都手动定义返回值接口会很繁琐。用Unpacked可以直接从函数返回值中提取内部类型,避免重复代码。比如多个函数都返回
Promise<ResponseData>,你不用每次都写ResponseData,直接用Unpacked<ReturnType<typeof xxx>>就能复用这个类型。
内容的提问来源于stack exchange,提问作者whowhenhow

