如何在TypeScript中使用switch case细化继承基础接口的接口?
在TypeScript中用switch case窄化继承自基础接口的类型
你的代码里没法正确窄化类型的原因,是用了泛型<T extends X>——TypeScript会把x当成所有X子类型的交集,而非你期望的A | B联合类型,自然没法在switch分支里识别具体子接口的专属属性。
要解决这个问题,只需要把函数参数类型改成A | B(或直接用X的联合子类型),去掉泛型声明即可:
interface X { type: string; } interface A extends X { type: 'a'; a: number; } interface B extends X { type: 'b'; b: string; } // 参数类型改为A | B,无需泛型 function processX(x: A | B) { switch (x.type) { case 'a': // TypeScript自动将x窄化为A类型,可安全访问a属性 console.log(x.a.toFixed(2)); break; case 'b': // 自动窄化为B类型,访问b属性无报错 console.log(x.b.toUpperCase()); break; default: // 新增default分支做穷尽检查,避免遗漏未知类型 const _exhaustiveCheck: never = x; throw new Error(`Unknown type: ${x.type}`); } }
核心原理
这里用到了TypeScript的判别式联合类型(Discriminated Unions):
- 所有子接口都继承了基础接口
X的type属性,且给type赋值了具体的字面量类型('a'、'b') - 当用
switch判断x.type时,TypeScript会根据字面量值自动把变量类型窄化到对应子接口,此时就能安全访问该子接口的独有属性。
如果必须保留泛型(比如需要返回和输入同类型的值),可以给泛型加上A | B的约束,这样也能实现类型窄化:
function processX<T extends A | B>(x: T): T { switch (x.type) { case 'a': x.a; // 正确识别为A类型 break; case 'b': x.b; // 正确识别为B类型 break; } return x; }
内容的提问来源于stack exchange,提问作者Fez Vrasta
相关产品推荐
相关产品推荐

