TypeScript中如何在泛型中使用类型参数推断?及函数报错解决
问题:为函数添加TypeScript类型约束时的泛型推断与报错解决
需求说明
- 函数接受两个参数:
- 包含
value属性的对象数组; - 回调函数,参数是第一个参数中所有对象的
value组成的数组。
- 包含
示例代码:
function fn( data, callback ) { callback( data.map( x => x.value ) ); }
尝试的TypeScript代码
class Data<T = any> { declare value: T; } type Modify<T extends unknown[]> = T extends [ first: infer F, ...args: infer U ] ? [ Data<F>, ...Modify<U> ] : []; type P = Modify<[ 'string', 'number' ]> // function fn<M>( atom: Data<M>, handler : ( value: M ) => void ): void; function fn<T extends any[]>( atoms: Modify<T>, handler : ( ...values: T ) => void ): void; function fn( atoms: Data | Data[], handler: ( ( value: any ) => void ) | ( ( ...values: any[] ) => void ) ): void { } // fn( new Data(), () => {} ); fn<[string, number]>( [ new Data<string>(), new Data<number>() ], () => { } ) fn( [ new Data() ], () => {} )
报错信息
Argument of type '[Data
]' is not assignable to parameter of type '[]'.
Source has 1 element(s) but target allows only 0.(2345)input.tsx(13, 10): The call would have succeeded against this implementation, but implementation signatures of overloads are not externally visible.
解决方案
问题出在泛型约束和重载的设计上,Modify<T>的递归逻辑无法在T为[any]时反向推断正确类型,导致TypeScript匹配到错误的重载签名。可以调整泛型参数的推断方向,直接从Data数组反向推导value的类型元组:
class Data<T = any> { declare value: T; } // 泛型T代表Data数组中每个元素的value类型组成的元组 function fn<T extends unknown[]>( atoms: { [K in keyof T]: Data<T[K]> }, handler: (...values: T) => void ): void { handler(...atoms.map(x => x.value) as T); } // 调用示例 fn([new Data<string>(), new Data<number>()], (str, num) => { // str: string, num: number }); fn([new Data()], (val) => { // val: any }); fn(new Data<boolean>(), (bool) => { // bool: boolean });
说明
- 用映射类型
{ [K in keyof T]: Data<T[K]> }让TypeScript自动从传入的atoms数组推断元组T的类型,每个位置的Data元素对应T中同位置的类型。 - 移除重载,单个泛型签名即可处理任意长度的
Data数组(包括单个元素场景)。 - 实现中的
as T是类型断言,因为map返回的是数组而非元组,需要明确告诉TypeScript其类型为元组T。
修改后所有调用场景都能正确推断类型,且不会出现原报错。
内容的提问来源于stack exchange,提问作者LCB
相关产品推荐
相关产品推荐

