TypeScript联合类型索引访问报错:类型'number | [number, number]'无属性'0'
问题原因
你遇到的问题是因为在解构函数参数时给isSingle设置了默认值false,破坏了TypeScript对联合类型IA的判别式类型窄化能力。原本IA是A1和A2的联合,isSingle是用来区分两个子类型的判别式,但默认值的加入让TypeScript无法再将isSingle的取值和value的类型准确关联起来——它会认为即使isSingle是false,value仍可能是number类型(因为默认值覆盖了联合类型的约束)。
解决方案
这里提供两种可靠的修复方式:
方案1:移除参数默认值,严格遵循联合类型约束
直接去掉isSingle = false的默认值,让调用者必须传入符合IA类型的完整参数,这样TypeScript就能正常通过isSingle的取值来窄化value的类型:
interface A1 { isSingle: true; value: number; } interface A2 { isSingle: false; value: [number, number]; } export type IA = A1 | A2; function A({ isSingle, value }: IA): void { if (!isSingle) { console.log(value[0]); // 此时TypeScript能确定value是[number, number] } }; export default A;
方案2:保留默认值,但在函数内部手动处理类型窄化
如果你需要保留isSingle的默认行为,可以把默认值的处理移到函数内部,同时使用类型断言或者自定义类型守卫来明确value的类型:
方式A:类型断言
interface A1 { isSingle: true; value: number; } interface A2 { isSingle: false; value: [number, number]; } export type IA = A1 | A2; function A(props: Partial<IA> = {}): void { const isSingle = props.isSingle ?? false; const value = props.value ?? (isSingle ? 0 : [0, 0]); if (!isSingle) { console.log((value as [number, number])[0]); } }; export default A;
方式B:自定义类型守卫
更严谨的方式是用类型守卫来确保类型安全:
interface A1 { isSingle: true; value: number; } interface A2 { isSingle: false; value: [number, number]; } export type IA = A1 | A2; function isA2(obj: IA): obj is A2 { return !obj.isSingle; } function A({ isSingle = false, value }: IA): void { if (isA2({ isSingle, value })) { console.log(value[0]); // 类型守卫明确value是A2的value类型 } }; export default A;
补充说明
判别式联合类型的核心是TypeScript能通过判别属性(比如这里的isSingle)自动关联对应的其他属性类型,一旦在解构或赋值时破坏了这种关联(比如添加默认值),类型窄化就会失效。所以优先推荐方案1,它能严格遵循TypeScript的类型系统设计,避免额外的类型断言或守卫代码。
内容的提问来源于stack exchange,提问作者Ali Ehyaie
相关产品推荐
相关产品推荐

