如何在TypeScript中判断对象联合类型并实现类型窄化?
解决TypeScript联合类型推断失效的问题
问题原因
当前代码中,handleType函数返回CA | CB联合类型,但TypeScript无法根据输入的具体值自动缩小这个联合类型的范围,导致result.unionKey无法正确提示对应属性。此外,直接使用'keyOne' in obj.unionKey进行类型判断时,虽然TypeScript能在局部缩小obj.unionKey的类型,但封装到函数后,类型关联丢失。
解决方案
方案1:给handleType添加泛型条件返回类型
通过泛型将输入类型与返回类型关联,让TypeScript根据输入的具体值推断出精确的返回类型:
type A = { keyOne: string; keyTwo: string; }; type B = { keyThree: string; keyFour: string; }; type C = { unionKey: A | B; keyFive: string; }; type CA = { unionKey: A; keyFive: string }; type CB = { unionKey: B; keyFive: string }; // 泛型函数,根据输入的unionKey类型返回对应类型 const handleType = <T extends C>(obj: T): T['unionKey'] extends A ? CA : CB => { if ('keyOne' in obj.unionKey) { return obj as CA; } else { return obj as CB; } }; // 此时TypeScript会自动推断result为CB类型 const result = handleType({ unionKey: { keyThree: 'sdfsd', keyFour: 'sadfasd' }, keyFive: 'sdfsd', }); result.unionKey.keyThree; // 自动提示生效 result.unionKey.keyFour; // 自动提示生效
方案2:使用类型守卫函数直接缩小类型
自定义类型守卫函数,在需要判断类型的地方直接使用,避免封装函数导致的类型关联丢失:
type A = { keyOne: string; keyTwo: string; }; type B = { keyThree: string; keyFour: string; }; type C = { unionKey: A | B; keyFive: string; }; type CA = { unionKey: A; keyFive: string }; type CB = { unionKey: B; keyFive: string }; // 判断是否为CA类型的守卫函数 function isCA(obj: C): obj is CA { return 'keyOne' in obj.unionKey; } // 判断是否为CB类型的守卫函数 function isCB(obj: C): obj is CB { return 'keyThree' in obj.unionKey; } const obj: C = { unionKey: { keyThree: 'test', keyFour: 'test' }, keyFive: 'test', }; if (isCA(obj)) { obj.unionKey.keyOne; // 提示A的属性 } else { obj.unionKey.keyThree; // 提示B的属性 }
方案3:重构为可区分联合类型(推荐)
给A和B添加一个专门的区分属性(比如type),让TypeScript能更可靠地自动缩小类型范围,这是最健壮的解决方案:
type A = { type: 'A'; // 区分属性 keyOne: string; keyTwo: string; }; type B = { type: 'B'; // 区分属性 keyThree: string; keyFour: string; }; type C = { unionKey: A | B; keyFive: string; }; const obj: C = { unionKey: { type: 'B', keyThree: 'test', keyFour: 'test' }, keyFive: 'test', }; // TypeScript自动将unionKey缩小为B类型 if (obj.unionKey.type === 'B') { obj.unionKey.keyThree; // 自动提示完美生效 }
内容的提问来源于stack exchange,提问作者amdev
相关产品推荐
相关产品推荐

