TypeScript带可选判别式的区分联合是否允许无效值赋值?
关于TypeScript联合类型与React Props的问题解答
首先看你给出的代码:
type P = | { foo: boolean; bar?: undefined } | { foo: boolean; bar: boolean; baz: boolean }; const p: P = { foo: true, baz: true };
这段代码能通过TypeScript检查,和你的预期不符,原因在于TypeScript的结构类型检查规则:对象只要匹配联合类型中任意一个分支的必填字段,就可以赋值。第一个分支{ foo: boolean; bar?: undefined }只要求foo是布尔值,bar可选(甚至可以完全不写),而额外的baz字段会被TypeScript忽略,所以{ foo: true, baz: true }能匹配第一个分支,自然不会报错。
要实现你预期的“只有两种有效值”,可以通过给分支添加禁止额外字段的约束来修正类型:
type P = | { foo: boolean; bar?: undefined; baz?: never } | { foo: boolean; bar: boolean; baz: boolean };
这里第一个分支把baz设为never类型且可选,意味着这个分支下baz不能有任何有效值(甚至不能出现在对象中),这样{ foo: true, baz: true }就会触发类型错误,完全符合你的预期。
至于你问的区分联合是否必须包含所有字段?答案是不需要,但要让TypeScript能明确区分不同分支,最稳妥且常用的方式是使用辨别符字段——也就是在所有联合分支中定义一个同名但类型不同的字段,比如:
type Props = | { foo: boolean; type: "simple" } | { foo: boolean; type: "complex"; bar: boolean; baz: boolean };
在React组件中,你可以通过props.type来判断当前属于哪个分支,TypeScript会自动帮你缩小类型范围,访问对应分支的专属字段时不会出现类型错误,这也是React props区分联合的标准写法。
如果不想用辨别符,也可以通过约束字段的互斥性来实现,但这种写法相对繁琐,远不如辨别符直观好维护。
内容的提问来源于stack exchange,提问作者mif
相关产品推荐
相关产品推荐

