如何让TypeScript自动推断函数返回值为元组而非数组?
让TypeScript自动推断getInvalidatorArgs返回值的元组类型
要解决TypeScript将getInvalidatorArgs返回对象的属性推断为数组而非元组的问题,核心是通过泛型约束建立invalidators中genSetKey的参数类型与getInvalidatorArgs返回值类型的强关联,让TypeScript自动识别元组类型,无需调用者手动添加类型注解。
步骤1:定义精确的Invalidator类型
先明确Invalidator的类型,将其genSetKey的参数类型作为泛型参数,确保元组类型能被后续泛型捕获:
type Invalidator<TArgs extends unknown[]> = { fn: () => void; // 可根据实际副作用逻辑调整fn的参数/返回值类型 genSetKey: (...args: TArgs) => string; // 明确接收元组类型参数 };
步骤2:重构辅助函数的泛型定义
在辅助函数的泛型中,显式关联invalidators的结构与getInvalidatorArgs的返回值类型,强制TypeScript推断元组而非数组:
function createCachedFunction< TFnArgs extends unknown[], TFnReturn, // 捕获传入的invalidators的结构,保留每个genSetKey的参数元组类型 TInvalidators extends Record<string, Invalidator<any>>, // 约束getInvalidatorArgs的返回值必须匹配每个invalidator的genSetKey参数元组 TInvalidatorArgs extends { [K in keyof TInvalidators]: Parameters<TInvalidators[K]['genSetKey']>; } >( primaryFn: (...args: TFnArgs) => TFnReturn, invalidators: TInvalidators, getInvalidatorArgs: (...args: TFnArgs) => TInvalidatorArgs ) { // 这里实现你的缓存逻辑:比如调用primaryFn后缓存结果,调用invalidator.fn时清除对应缓存键 return (...args: TFnArgs) => { const result = primaryFn(...args); // 示例:获取invalidator参数并生成缓存键 const invalidatorArgs = getInvalidatorArgs(...args); Object.entries(invalidators).forEach(([key, invalidator]) => { const setKey = invalidator.genSetKey(...invalidatorArgs[key as keyof TInvalidatorArgs]); console.log(`Cache key to invalidate: ${setKey}`); }); return result; }; }
步骤3:使用示例(无需手动加类型注解)
调用辅助函数时,TypeScript会自动根据invalidators中genSetKey的参数类型,推断getInvalidatorArgs返回对象的属性为元组类型:
// 示例:可缓存的主函数 function getUser(name: string, lastName: string): { id: number; name: string } { return { id: 123, name: `${name} ${lastName}` }; } // 示例:缓存失效器集合 const userInvalidators = { updateUser: { fn: () => console.log('Invalidating user cache'), genSetKey: (name: string, lastName: string) => `user:${name}:${lastName}` }, deleteUser: { fn: () => console.log('Deleting user cache'), genSetKey: (userId: number) => `user:id:${userId}` } }; // 调用辅助函数,无需任何手动类型注解 const cachedGetUser = createCachedFunction( getUser, userInvalidators, (name, lastName) => ({ updateUser: [name, lastName], // 自动推断为[string, string]元组 deleteUser: [123] // 自动推断为[number]元组 }) ); // 测试调用 cachedGetUser('John', 'Doe');
原理说明
通过泛型TInvalidatorArgs约束为TInvalidators中每个genSetKey的参数元组的映射,TypeScript会基于invalidators的类型信息,自动将getInvalidatorArgs返回的数组字面量推断为匹配的元组类型,而非默认的宽泛数组类型(如string[])。
内容的提问来源于stack exchange,提问作者lentil-soup
相关产品推荐
相关产品推荐

