从一个复杂的泛型参数的函数签名深入理解typescript关于泛型的类型推断

以下是nuxt3中useFetch的函数签名,看起来很长有点乱对不对,但这还是我优化格式后的结果,不然更难看(原始的代码是在同一行里显示),泛型参数部分看红色的左右尖括号 里的部分(各个泛型参数用红色的逗号隔开),

export declare function useFetch<ResT = void**,** ErrorT = FetchError**,**

ReqT extends NitroFetchRequest = NitroFetchRequest**,**

Method extends AvailableRouterMethod<ReqT> = ResT extends void ? 'get' extends AvailableRouterMethod<ReqT> ? 'get' : AvailableRouterMethod<ReqT> : AvailableRouterMethod<ReqT>,

_ResT = ResT extends void ? FetchResult<ReqT, Method> : ResT**,**

DataT = _ResT**,**

PickKeys extends KeysOf<DataT> = KeysOf<DataT>,

DefaultT = null**>**(request: Ref<ReqT> | ReqT | (() => ReqT), opts?: UseFetchOptions<_ResT, DataT, PickKeys, DefaultT, ReqT, Method>): AsyncData<PickFrom<DataT, PickKeys> | DefaultT, ErrorT | null>;

这里重点通过类型推导说明:为什么ResT 就一定是useFetch的返回类型

首先看最后一行的返回值类型:

AsyncData<PickFrom<DataT, PickKeys> | DefaultT, ErrorT | null>

这也是一个泛型,首先不考虑外围AsyncData的包装,它直接跟PickFrom里面的有关系,

从字面意思也可以理解到PickFrom是:从DataT类型中挑选出key值为PickKeys所对应的类型,

那么基本可以断定AsyncData的类型最终跟DataT的类型有关

而泛型参数列表中有个定义:DataT = _ResT,就是说DataT类型取决于_ResT

而_ResT = ResT extends void ? FetchResult<ReqT, Method> : ResT

这句话的意思是如果ResT类型为空,则_ResT类型为FetchResult<ReqT, Method>,否则_ResT类型就是ResT, 一句话_ResT类型取决于ResT的类型。

所以根据链式关系: DataT =》 _ResT =》 ResT,可以得出: DataT类型取决于 ResT的类型

AsyncData的类型最终跟DataT的类型有关,所以AsyncData类型也取决于ResT的类型

所以ResT的类型就是useFetch函数的返回类型

但这还不够,需要继续深挖,证明这个结论==》AsyncData的类型取决于DataT的类型

对于PickFrom<DataT, PickKeys>,我们不去深究,这个基本可以判断:必定取决于DataT类型

重点要看AsyncData部分的定义

export interface _AsyncData<DataT, ErrorT> {

data: Ref<DataT>;

pending: Ref<boolean>;

refresh: (opts?: AsyncDataExecuteOptions) => Promise<DataT>;

execute: (opts?: AsyncDataExecuteOptions) => Promise<DataT>;

error: Ref<ErrorT | null>;

status: Ref<AsyncDataRequestStatus>;

}

export type AsyncData<Data, Error> = _AsyncData<Data, Error> & Promise<_AsyncData<Data, Error>>;

从上面的代码可以看到:AsyncData取决于_AsyncData,而_AsyncData的类型的真正数据是data属性,而data正是AsyncData的第一个泛型参数:Data, 而Data相当于上面的

PickFrom<DataT, PickKeys> | DefaultT, 这个值直接跟DataT类型有关

所以这里就证明了: AsyncData的类型确实取决于DataT的类型,而 DataT类型又取决于 ResT的类型,所以****AsyncData的类型最终取决于ResT的类型,而AsyncData是useFetch函数返回值类型,那么可以推断出==》ResT类型就是useFetch函数的返回值类型

相关推荐
柯克七七13 小时前
我把 bug 修得太干净了,测试组以为这个模块本来就没问题
前端·javascript·typescript
退休倒计时14 小时前
【每日一题】LeetCode 39. 组合总和 TypeScript
算法·leetcode·typescript
yyt36304584114 小时前
KlineChartQuant Tooltip 高频交互 200FPS 性能优化完整复盘
前端·经验分享·性能优化·typescript·vue·交互·chrome devtools
用户09340777351419 小时前
HarmonyOS WPS Open SDK 实践:办公审批附件「打开—编辑—回传」代码实现
typescript·harmonyos
Flynt19 小时前
TypeScript 5.8 让我少踩了一个大坑,顺手再聊聊 --erasableSyntaxOnly
前端·javascript·typescript
退休倒计时2 天前
【每日一题】LeetCode 17. 电话号码的字母组合 TypeScript
算法·leetcode·typescript
无情的西瓜皮3 天前
MCP 协议实战:从零搭建一个 MCP 服务器(Node.js 版)
vue.js·人工智能·typescript·node.js
退休倒计时3 天前
【每日一题】LeetCode 78. 子集 TypeScript
算法·leetcode·typescript
学习-学习3 天前
Node.js 现在能直接跑 TypeScript 了?Type Stripping 原理、限制与 tsx / ts-node 取舍
typescript·node.js
yume_sibai3 天前
大屏数据可视化 - 边框红绿呼吸灯实现详解
前端·信息可视化·typescript