function transformArray<T, U>(arr: T[], transform: (arg: T) => U): U[] {
return arr.map(transform);
}
类型推断在泛型约束条件下的工作原理
- 类型参数定义:
transformArray
函数使用了两个类型参数T
和U
。T
表示输入数组arr
的元素类型,U
表示转换函数transform
的返回类型。
- 类型推断过程:当调用
transformArray
时,TypeScript会根据传入的实际参数推断T
和U
的具体类型。对于T
,它会从传入的数组arr
中推断出数组元素的类型。例如,如果传入[1, 2, 3]
,T
会被推断为number
。对于U
,它会从转换函数transform
的返回值推断。例如,如果转换函数是(num: number) => num.toString()
,那么U
会被推断为string
。
- 泛型约束作用:这里虽然没有显式写泛型约束(如
T extends SomeType
这种形式),但实际上函数签名本身就隐含了约束。transform
函数的输入参数类型必须是T
,这就确保了转换函数的输入类型与数组元素类型匹配。
可能遇到的类型推断陷阱及避免方法
- 陷阱:
- 函数重载模糊:如果有多个重载版本的
transform
函数,TypeScript可能无法正确推断类型。例如,假设有transform
函数既可以接受string
返回number
,又可以接受number
返回string
,在调用transformArray
时,TypeScript可能无法确定应该使用哪个重载版本,导致类型推断错误。
- 复杂类型推断失败:当转换函数的返回类型是复杂类型(如函数返回一个对象,对象的属性类型依赖于输入参数),TypeScript可能无法准确推断。例如,
(obj: {a: number}) => ({b: obj.a.toString()})
,TypeScript可能无法正确推断出返回对象的类型细节。
- 避免方法:
- 明确类型参数:在调用
transformArray
时,显式指定类型参数。例如,transformArray<number, string>([1, 2, 3], (num) => num.toString())
,这样可以避免因函数重载模糊导致的类型推断错误。
- 使用类型别名或接口:对于复杂类型,定义类型别名或接口来明确转换函数的输入和输出类型。例如,定义
interface Input { a: number; }
和interface Output { b: string; }
,然后transformArray<Input, Output>([{a: 1}], (obj: Input) => ({b: obj.a.toString()} as Output))
,通过这种方式可以帮助TypeScript更准确地进行类型推断。