如何正确声明generic Types泛型类型?
泛型类型正确声明的实操方案
常见的声明踩坑点
- 泛型参数顺序颠倒:把需要手动指定的泛型放在了可自动推导的参数前面,导致TS没法从函数入参自动收窄类型,调用时必须手动补全所有泛型参数,写起来冗余还容易错。最典型的就是写请求封装时把泛型写成
function request<T, R>(url: T): Promise<R>,因为返回值类型R没有入参推导来源,TS根本没法自动识别。 - 泛型之间缺乏关联约束:把存在映射关系的类型做成完全独立的泛型,比如请求入参的URL和接口返回值没有建立类型映射,导致类型校验完全形同虚设。
- 泛型约束写空:只给泛型加了
extends的宽泛约束,没有把泛型和实际的入参、返回值做类型关联,最后出现“类型不匹配但TS不报错”的问题。
可直接复用的声明逻辑
按照TS泛型的推断规则,遵循两个核心原则写声明就能解决大部分这类问题:
- 泛型参数排序:可自动推导的参数放最前面,需要手动覆盖的可选参数放最后面
- 映射关系绑定:通过
keyof、索引访问类型把入参的取值和对应的返回值类型做强制绑定,让TS能顺着入参自动匹配返回类型
对应实现代码示例
// 提前定义所有接口路径和对应返回值的类型映射 interface ApiTypeMap { '/user/info': { userId: number; nickname: string; avatarUrl: string } '/article/hot': { articleId: number; title: string; viewCount: number }[] } // 正确的泛型声明 function fetchApi<T extends keyof ApiTypeMap>( targetUrl: T, extraConfig?: Omit<RequestInit, 'url'> ): Promise<ApiTypeMap[T]> { return fetch(targetUrl, extraConfig).then(response => response.json()) } // 调用时无需手动传泛型,TS会自动根据传入的URL推导返回值类型 fetchApi('/user/info').then(res => { res.userId // 自动推导为number,无类型报错 })
内容的提问来源于stack exchange,提问作者Pilki
相关产品推荐
相关产品推荐

