TypeScript中使用联合类型变量时能否获知对象的确切类型?
核心原因
你运行console.log(typeof c)输出object是正常结果,本质原因有两个:
- TypeScript的类型系统仅在编译阶段生效:所有接口、类型标注、联合类型这些TS专属的语法,在编译为JavaScript运行时都会被完全擦除,JS运行环境根本感知不到你定义过
Car、Bike这两个接口,自然不可能返回对应的类型名称。 typeof是JavaScript原生的运行时操作符:它本身就只能识别JS内置的基础类型,返回值只有string/number/boolean/undefined/object/function/symbol/bigint这几种,对于自定义结构的对象,统一返回object,不具备识别自定义结构类型的能力。
补充一点你这段代码的编译时逻辑:TS是结构化类型系统,只要结构满足接口要求就判定类型匹配,你赋值的{gears: 2}完全符合Car接口的定义(缺少Bike接口要求的必填model字段,不可能是Bike),所以编译阶段TS其实能判定此时c的类型是Car,但这个判断结果不会留存到运行阶段。
运行时区分联合类型的实现方式
由于TS的类型擦除特性,要在运行时判断联合类型的具体成员,需要手动实现类型守卫,针对你的场景有两种常用方案:
1. 添加判别式字段(推荐)
给两个接口增加一个值为字面量类型的专属标记字段,运行时直接判断这个字段的值即可,TS也能基于这个判断自动做编译时的类型收窄:
interface Car { kind: 'car' gears: number } interface Bike{ kind: 'bike' gears: number, model: string } let c: Bike | Car; c = {kind: 'car', gears : 2}; if (c.kind === 'car') { // 此处TS自动将c收窄为Car类型 console.log('当前变量是Car') } else { // 此处TS自动将c收窄为Bike类型,可以直接访问model属性 console.log('当前变量是Bike,型号为:', c.model) }
2. 判断独有属性是否存在
你的两个接口里,Bike存在独有的model字段,Car没有这个字段,可以用in操作符判断属性是否存在来区分类型:
let c: Bike | Car; c = {gears : 2}; if ('model' in c) { // 收窄为Bike console.log('当前变量是Bike') } else { // 收窄为Car console.log('当前变量是Car') }
内容的提问来源于stack exchange,提问作者Diego Alves
相关产品推荐
相关产品推荐

