如何在TypeScript中对string类型与字面量类型做类型分支判断?
问题原因
报错本质是 TypeScript 无法对当前的联合类型 T 完成正确的类型窄化:联合类型第一个分支的 type 类型是通用 string,字面量 "foo" 属于 string 的子集,所以当你判断 foo.type === "foo" 时,TypeScript 认为两个分支的类型都有可能命中,无法排除掉没有 bar 属性的第一个分支,因此抛出属性不存在的错误。
解决方案
- 方案1:调整联合类型的定义,让两个分支的
type字段互斥
把第一个分支的type类型改为排除"foo"的字符串类型,这样 TypeScript 就可以通过type字段的判断正确窄化类型:
type T = | { type: Exclude<string, "foo">; } | { type: "foo"; bar: number; }; const func = (foo: T) => { if (foo.type === "foo") { // 此时可以正确识别foo的类型为第二个分支,bar属性存在 return foo.bar } }
- 方案2:自定义类型守卫实现类型窄化
如果不能修改原有的T类型定义,可以手写类型守卫函数,主动告诉 TypeScript 判定逻辑对应的类型规则:
type T = | { type: string; } | { type: "foo"; bar: number; }; // 自定义类型守卫 const isFooType = (val: T): val is Extract<T, {type: "foo"}> => { return val.type === "foo" } const func = (foo: T) => { if (isFooType(foo)) { return foo.bar } }
- 方案3:使用类型断言(兜底方案,不推荐)
如果你确定当前分支下foo一定存在bar属性,可以直接用类型断言跳过 TypeScript 的检查,但是这种方式会丢失类型校验能力,只有在你确认逻辑没问题的情况下使用:
const func = (foo: T) => { if (foo.type === "foo") { return (foo as Extract<T, {type: "foo"}>).bar } }
内容的提问来源于stack exchange,提问作者islandryu
相关产品推荐
相关产品推荐

