TypeScript:能否为数组每个元素单独推断类型参数?
问题描述
现有以下TypeScript代码:
// a value, and a function that will be called with this value type ValueAndHandler<T> = [value: T, handler: (value: T) => void] type Params = { // not sure how to type it valuesAndHandlers: ValueAndHandler<???>[] // it's not the only field in the structure // so I cannot just pass array as variadic arguments otherStuff: number } function doSomethingWithParams(params: Params){/* something, not important*/} doSomethingWithParams({ // array of some pairs of handlers and values // each value is only related to its handler, and not to other handlers/values valuesAndHandlers: [ [5, value => console.log(value.toFixed(3))], ["example", value => console.log(value.length)] ], otherStuff: 42 })
需要实现的效果是:第一个handler的参数类型自动推断为number,第二个handler的参数类型自动推断为string,但当前定义下所有元素共享同一泛型类型,无法实现单独推断。
解决方案
通过将函数声明为泛型,让TypeScript能逐个推断数组中每个ValueAndHandler的具体类型:
type ValueAndHandler<T> = [value: T, handler: (value: T) => void] // 将函数设置为泛型,泛型参数T约束为ValueAndHandler组成的数组 function doSomethingWithParams<T extends ValueAndHandler<unknown>[]>(params: { valuesAndHandlers: T otherStuff: number }) {/* 原有逻辑 */} doSomethingWithParams({ valuesAndHandlers: [ [5, value => console.log(value.toFixed(3))], // value自动推断为number ["example", value => console.log(value.length)] // value自动推断为string ], otherStuff: 42 })
或者也可以将Params定义为泛型类型,达到同样效果:
type ValueAndHandler<T> = [value: T, handler: (value: T) => void] // Params接受泛型参数T,对应valuesAndHandlers数组的元素类型集合 type Params<T extends unknown[]> = { valuesAndHandlers: { [K in keyof T]: ValueAndHandler<T[K]> } otherStuff: number } function doSomethingWithParams<T extends unknown[]>(params: Params<T>) {/* 原有逻辑 */}
原理说明
之前的问题在于Params中的valuesAndHandlers被定义为单一泛型参数的数组(ValueAndHandler<???>[]),这强制要求数组中所有元素必须是同一种ValueAndHandler类型。
通过将函数(或Params类型)设置为泛型,让泛型参数覆盖整个数组的类型后,TypeScript会对数组中的每个元素单独进行类型推断,确保每个handler的参数类型和对应value的类型严格匹配,同时保留otherStuff等其他字段的定义。
内容的提问来源于stack exchange,提问作者Nartallax
相关产品推荐
相关产品推荐

