如何通过属性类型守卫自动细化Box父对象的类型?
如何自动细化Box的类型参数无需自定义类型守卫?
先看基础类型定义:
type StateA = { type: "A"; a: number }; type StateB = { type: "B"; b: string }; type State = StateA | StateB; interface Box<T extends State = State> { state: T; }
当前问题:直接检查state.type时,TypeScript能正确细化b.state的类型,但无法把整个Box实例的类型参数细化为StateB:
const b: Box = { state: { type: "B", b: "str" } }; if (b.state.type === "B") { console.log(b.state.b); // 类型推断正常 const bRefined: Box<StateB> = b; // 报错:无法将类型Box<State>分配给Box<StateB> }
自定义类型守卫能解决,但我们需要更自动的方案,以下是两种可行方法:
方法一:将Box定义为带判别式的联合类型
把泛型接口Box<T>改成对应每个State子类型的联合类型,让TypeScript通过state.type自动细化整个Box的类型:
type StateA = { type: "A"; a: number }; type StateB = { type: "B"; b: string }; type State = StateA | StateB; // 重构Box为联合类型,与State的判别式联动 type Box = | { state: StateA } | { state: StateB }; // 使用示例 const b: Box = { state: { type: "B", b: "str" } }; if (b.state.type === "B") { console.log(b.state.b); const bRefined: { state: StateB } = b; // 无报错,类型自动匹配 }
这种方式完全利用TypeScript的原生联合类型判别式支持,不需要额外编写类型守卫。
方法二:让TypeScript自动推导变量的具体泛型类型
避免直接把变量声明为Box(不带泛型参数会默认是Box<State>),让TypeScript在变量创建时自动推导更具体的泛型类型:
// 不指定类型,TS自动推导为Box<StateB> const b = { state: { type: "B", b: "str" } }; if (b.state.type === "B") { const bRefined: Box<StateB> = b; // 无报错 }
如果必须显式声明类型,可以直接标注具体泛型:
const b: Box<StateB> = { state: { type: "B", b: "str" } };
补充:const断言的快捷方式
如果是字面量创建的实例,可以用const断言让TypeScript推导最精确的类型:
const b = { state: { type: "B", b: "str" } } as const; const bRefined: Box<StateB> = b; // 直接赋值成功
内容的提问来源于stack exchange,提问作者Marcus Riemer
相关产品推荐
相关产品推荐

