TypeScript如何让函数识别参数为两个接口类型之一?
解决TypeScript联合类型参数的类型识别问题
我有个函数,参数是两种不同的payload联合类型,代码如下:
interface payload1 { userId: string; partnerId: string; } interface payload2 { userToken: string; partnerKey: string; } function loadData(input: payload1 | payload2){ if(input.userId){ // 通过userId加载数据 } }
但TypeScript报错:Property 'userId' does not exist on type 'payload1 | payload2'. Property 'userId' does not exist on type 'payload2'.
下面是几种让TypeScript正确识别参数类型的方法:
方法一:用in操作符做类型守卫
直接检查属性是否存在,TypeScript会自动窄化类型:
function loadData(input: payload1 | payload2){ if('userId' in input){ // 这里input会被识别为payload1类型 console.log(input.userId, input.partnerId); } else { // 这里自动识别为payload2类型 console.log(input.userToken, input.partnerKey); } }
方法二:自定义类型守卫函数
如果需要更复杂的判断逻辑,可以写专门的类型守卫函数:
function isPayload1(input: payload1 | payload2): input is payload1 { return (input as payload1).userId !== undefined; } function loadData(input: payload1 | payload2){ if(isPayload1(input)){ console.log(input.userId); } else { console.log(input.userToken); } }
方法三:给接口添加区分字段(推荐)
如果能修改接口定义,添加一个唯一的区分字段是最清晰的方案,属于TypeScript的可辨识联合类型:
interface payload1 { type: 'user-id'; // 唯一标识字段 userId: string; partnerId: string; } interface payload2 { type: 'user-token'; // 唯一标识字段 userToken: string; partnerKey: string; } function loadData(input: payload1 | payload2){ if(input.type === 'user-id'){ console.log(input.userId); } else { console.log(input.userToken); } }
原因说明
TypeScript处理联合类型时,只有当判断条件能明确区分出具体类型时,才会自动进行类型窄化。直接访问input.userId会报错,因为payload2没有这个属性,TS无法确定当前参数的具体类型。上面几种方法都能让TS明确当前分支的类型,从而正确识别属性。
内容的提问来源于stack exchange,提问作者mdunisch
相关产品推荐
相关产品推荐

