TypeScript如何判别联合类型单个分支并实现未匹配时接口回退
实现方法
你原来的代码不生效,核心问题是TypeScript可辨识联合的判定规则:联合类型的各分支需要通过判别字段(这里是type)做互斥区分,你写的ActionHistoryDefault里type覆盖了所有枚举值(包含create),和ActionHistoryInsert的判别值重叠,类型收窄时会把两个分支的entityId做合并,自然得不到预期的undefined类型。
要实现「命中特定分支走专属类型、未命中自动回退通用接口」的逻辑,只需要把通用接口的判别字段范围,设置为排除所有特殊分支已占用的判别值,从根源上避免分支判别值重叠即可:
enum ActionType { create = 'create', delete = 'delete', update = 'update', } // 特殊分支:type固定为单个枚举值,定义专属字段规则 interface ActionHistoryInsert { type: ActionType.create entityId: undefined; entityType: string; } // 通用接口:type范围排除所有特殊分支占用的枚举值,剩余类型自动走通用规则 interface ActionHistoryDefault { type: Exclude<ActionType, ActionHistoryInsert['type']>; entityId: number | string | undefined; entityType: string; } type ActionHistoryOptions = ActionHistoryDefault | ActionHistoryInsert declare const a: ActionHistoryOptions if (a.type === ActionType.create) { a.entityId // 这里TS会自动推导为undefined,完全符合预期 } else { // 此处a.type为delete/update,自动回退到通用接口类型 a.entityId // 类型为number | string | undefined }
扩展场景
如果后续要加更多特殊分支,只需要在通用接口的Exclude参数里追加对应特殊分支的type即可,比如新增update的特殊处理:
interface ActionHistoryUpdate { type: ActionType.update entityId: string; entityType: string; } // 通用接口排除create、update两个特殊分支,剩余的delete自动走通用逻辑 interface ActionHistoryDefault { type: Exclude<ActionType, ActionHistoryInsert['type'] | ActionHistoryUpdate['type']>; entityId: number | string | undefined; entityType: string; } type ActionHistoryOptions = ActionHistoryDefault | ActionHistoryInsert | ActionHistoryUpdate
所有没有被特殊分支显式声明的枚举值,都会自动匹配通用接口,不需要额外维护分支映射关系。
内容的提问来源于stack exchange,提问作者nook。
相关产品推荐
相关产品推荐

