TypeScript中使用接口Union Types仅能访问共有属性如何解决
TypeScript联合类型无法访问接口独有属性的解决方案
联合类型默认仅允许访问所有成员的共有属性是TypeScript的类型安全保护机制,要访问不同接口的独有属性,需要通过类型收窄将变量类型从宽泛的联合类型确定为具体的某一个接口类型,常用实现方式如下:

可辨识联合(优先推荐)
给联合类型的每个接口添加一个值为字面量类型的同名共有属性(通常命名为type或kind),之后通过判断这个属性的值,TypeScript就能自动完成类型收窄:
// 为两个接口添加判别字段type interface User { type: 'user'; name: string; userId: number; // User独有属性 } interface Admin { type: 'admin'; name: string; adminId: number; // Admin独有属性 } type Person = User | Admin; function getInfo(person: Person) { // 共有属性name可直接访问 console.log(person.name); // 通过判别字段收窄类型 if (person.type === 'user') { // 此处TS自动推导person为User类型,可安全访问userId console.log(person.userId); } else { // 此处TS自动推导person为Admin类型,可安全访问adminId console.log(person.adminId); } }
用
in操作符判断属性存在
如果不方便修改原有接口添加判别字段,可以用in操作符判断独有属性是否存在于当前对象上,TS会根据判断结果自动收窄类型:
interface User { name: string; userId: number; } interface Admin { name: string; adminId: number; } type Person = User | Admin; function getInfo(person: Person) { console.log(person.name); if ('userId' in person) { // 存在userId属性,收窄为User类型 console.log(person.userId); } else { // 不存在userId则为Admin类型 console.log(person.adminId); } }
用类型谓词封装复杂判断逻辑
如果类型判断逻辑较复杂,可以封装为专门的类型判断函数,通过类型谓词(返回值格式为参数 is 具体类型)明确告诉TS类型收窄规则:
function isUser(person: Person): person is User { // 编写自定义判断逻辑,例如判断userId是否为数字类型 return typeof (person as User).userId === 'number'; } function getInfo(person: Person) { console.log(person.name); if (isUser(person)) { console.log(person.userId); } else { console.log(person.adminId); } }
注意:尽量避免直接使用
as做强制类型转换,这种方式会跳过TS的类型校验,如果实际类型和声明类型不一致,会引发运行时错误。
内容的提问来源于stack exchange,提问作者epicmet
相关产品推荐
相关产品推荐

