TypeScript泛型返回类型子类型参数的约束与类型兼容问题
TypeScript代码问题修复方案
核心问题对应修复
1. 保证startValues与endValues类型匹配
原Anim类泛型约束为Partial<Values>,导致传入XY这类完整类型时,强制要求参数包含所有属性。调整后让Anim泛型直接约束为Values的子集,transform方法新增泛型U extends Partial<T>,确保传入的start和end是同类型的部分属性对象,既允许传入部分字段,又保证两者类型完全一致。
2. 解决值聚合的类型错误
原代码中TypeScript无法确定T[key]的具体类型,导致赋值报错。通过将结果对象断言为{ [K in keyof U]: number },明确返回的每个属性都是number类型;同时对循环中的属性值做类型断言,因为U是Partial<T>,而T的属性均为number,只要属性存在就必然是number类型。
3. 获取无undefined的返回类型
通过指定返回类型为{ [K in keyof U]: number },确保返回对象的所有属性都是必填的number类型,不存在undefined,因为循环中已为每个存在的key赋值了计算后的number值。
修正后的完整代码
type Values = Record<string, number> // 泛型约束为Values的子集,而非Partial<Values> class Anim<T extends Values> { // 接受同类型的Partial<T>参数,保证start和end类型匹配 transform<U extends Partial<T>>({ startValues, endValues }: { startValues: U, endValues: U }) { // 断言结果类型为所有属性都是number的对象 const result = { ...startValues } as { [K in keyof U]: number } for (const key in startValues) { // 断言属性值为number,消除undefined警告 const startVal = startValues[key] as number const endVal = endValues[key] as number const val = startVal + endVal result[key] = val } return result } } type XY = { x: number, y: number } class Point { anim = new Anim<XY>() transform(...args: Parameters<Anim<XY>["transform"]>) { const val = { x: 0, y: 0 } const diff = this.anim.transform(...args) // 将Object.keys的结果断言为diff的具体键数组,解决索引签名报错 (Object.keys(diff) as Array<keyof typeof diff>).forEach(key => { val[key] += diff[key] }) return val } } const p = new Point() // 现在可以正常传入Partial<XY>类型的参数,无属性缺失报错 const result = p.transform({ startValues: { x: 0 }, endValues: { x: 10 } }) const val = result.x + 5 // result类型为{ x: number },可正常访问属性
内容的提问来源于stack exchange,提问作者Sean
相关产品推荐
相关产品推荐

