TypeScript中如何强制实现符合属性约束的可辨识联合类型
TypeScript 联合类型严格属性校验实现
问题复现
当前类型定义无法拦截缺失属性的非法赋值,原始代码如下:
type UrlCellRendererProps = { prop1: string; }; type GroupByCellRendererProps = { prop2: boolean; prop3: number; }; type TEST = UrlCellRendererProps | (UrlCellRendererProps & GroupByCellRendererProps) // 预期合法 const a: TEST = { prop1: 'url', } // 预期合法 const b: TEST = { prop1: 'url', prop2: true, prop3: 13 } // 预期非法,实际TS未报错:缺失prop3 const c: TEST = { prop1: 'url', prop2: true, } console.log(a)
失效原因
TypeScript 采用结构化类型判定规则,只要对象满足联合类型任意一个成员的必填属性要求,就会被判定为类型合法。定义的UrlCellRendererProps仅要求存在prop1字段,因此即使对象额外携带prop2、缺失prop3,TS依然会判定它匹配第一个联合分支,不会抛出类型错误。
解决方案
方案1:通过never禁止分支出现无关属性(无需新增字段)
在仅需prop1的联合分支中,将GroupBy场景的专属属性设置为可选的never类型,明确禁止这些属性出现在该分支中,即可实现严格校验:
type UrlCellRendererProps = { prop1: string; // 明确禁止该分支出现GroupBy相关属性 prop2?: never; prop3?: never; }; type GroupByCellRendererProps = { prop2: boolean; prop3: number; }; type TEST = UrlCellRendererProps | (UrlCellRendererProps & GroupByCellRendererProps) // 校验通过 const a: TEST = { prop1: 'url', } // 校验通过 const b: TEST = { prop1: 'url', prop2: true, prop3: 13 } // 抛出类型错误:prop3缺失 const c: TEST = { prop1: 'url', prop2: true, }
方案2:添加可辨识标签(标准可辨识联合写法)
如果业务场景允许新增类型标识字段,该写法语义更清晰,TS类型推断稳定性更高:
type UrlCellRendererProps = { cellType: 'url'; // 可辨识区分标签 prop1: string; }; type GroupByCellRendererProps = { cellType: 'groupBy'; // 可辨识区分标签 prop1: string; prop2: boolean; prop3: number; }; type TEST = UrlCellRendererProps | GroupByCellRendererProps // 校验通过 const a: TEST = { cellType: 'url', prop1: 'url', } // 校验通过 const b: TEST = { cellType: 'groupBy', prop1: 'url', prop2: true, prop3: 13 } // 抛出类型错误:cellType为groupBy时缺失必填属性prop3 const c: TEST = { cellType: 'groupBy', prop1: 'url', prop2: true, }
内容的提问来源于stack exchange,提问作者Matan Gubkin
相关产品推荐
相关产品推荐

