非泛型queryData函数的参数类型匹配校验可行性咨询
问题背景
假设我们拥有如下用于从API获取数据的抽象实现:
- 用于存储数据的类
class DataItem<T> { data?: T | null }
- 用于执行查询的函数
function queryData ( fn: () => Promise<any>, item: DataItem<any>, transformResponse?: (value: any) => any // value为fn的执行结果 )
我们期望按照如下方式调用该函数:
const item = new DataItem<ItemDto>() async function request (): Promise<ItemDto> { // 业务请求逻辑 } queryData( () => request(), item )
核心诉求:不将queryData定义为需要调用方手动传参的泛型函数的前提下,实现以下3项类型校验能力:
- 校验函数
fn的返回结果类型与item中存储的类型是否匹配 - 若传入
transformResponse函数,校验其返回值类型与item的类型匹配 - 若传入
transformResponse函数,校验其入参value的类型与fn函数的返回值类型一致
实现方案
完全可以实现,核心是利用TypeScript的上下文类型推断和泛型自动关联能力,不需要调用方感知泛型的存在,只需要在函数参数的类型定义中加入内部自动推导的泛型约束即可,调用体验和普通非泛型函数完全一致。
具体修改后的类型定义如下,原有业务逻辑不需要调整:
function queryData< ItemType, FnReturnType extends ItemType, TransformReturnType extends ItemType = FnReturnType >( fn: () => Promise<FnReturnType>, item: DataItem<ItemType>, transformResponse?: (value: Awaited<FnReturnType>) => TransformReturnType ) { // 原有内部实现逻辑保持不变 }
三项校验能力的实现逻辑:
- 针对
fn返回值和item类型的匹配校验:FnReturnType extends ItemType约束会先从传入的item实例中自动提取DataItem对应的存储类型ItemType,再检查fn返回的Promise解析结果类型是否可赋值给ItemType,类型不匹配时会直接抛出类型错误 - 针对
transformResponse返回值和item类型的匹配校验:TransformReturnType extends ItemType约束会强制要求转换函数的返回值必须可赋值给item的存储类型,不满足约束时直接报错 - 针对
transformResponse入参和fn返回值的匹配校验:转换函数的入参value类型直接定义为Awaited<FnReturnType>,也就是fn返回Promise的解析结果类型,TypeScript会自动做上下文类型校验,入参类型不匹配时直接报错
说明:这里声明的泛型完全是TypeScript内部根据传入参数自动推导的,调用
queryData时不需要手动传入任何泛型参数,和调用普通非泛型函数的体验没有区别。通常所说的"泛型函数"指的是需要调用方显式传入泛型参数、泛型属于函数对外暴露API一部分的场景,这种仅用于内部类型推导的泛型对调用方完全透明,不会增加额外使用成本。
实际使用时所有错误场景都会被正确拦截:包括fn返回类型与item存储类型不匹配、转换函数返回值与item类型不匹配、转换函数入参与fn返回值类型不匹配等问题,TypeScript都会在编译阶段及时报出类型错误。
内容的提问来源于stack exchange,提问作者Amanaemonesia
相关产品推荐
相关产品推荐

