针对本地字面量对象的类型检查生效,但同值变量的类型检查不生效的原因咨询
针对本地字面量对象的类型检查生效,但同值变量的类型检查不生效的原因咨询
我的问题场景
最近用TypeScript写表单组件的时候碰到个奇怪的事儿:我给表单的defaultValues传值,本来是想靠TS的类型检查,把那些目标对象里根本不存在的属性给拦下来。结果发现两种写法的检查结果完全不一样:
- 直接传本地字面量对象的时候,比如这么写:
这里的<FilterForm defaultValues={{ name: "Alice", something: "oops" }} />something会立刻被TS标红,提示它不是目标类型里的属性,这完全是我想要的效果! - 但如果我把完全一样的对象先存到变量里再传,比如:
这时候TS居然一点反应都没有,完全不报错!明明值是一模一样的,为啥检查结果差这么多啊?const defaultVals = { name: "Alice", something: "oops" }; <FilterForm defaultValues={defaultVals} />
搞懂背后的原因
其实这都是TypeScript的字面量类型自动拓宽在搞怪:
- 当你直接把字面量对象传给组件属性时,TS会开启严格的字面量检查模式,它会精准对比这个对象和组件要求的
defaultValues类型,只要多了不该有的属性,立刻就会报错。 - 可一旦你把字面量赋值给变量,TS默认会把这个变量的类型“放宽”——比如上面的
defaultVals,TS不会把它限制成和字面量完全一致的类型,而是推断成更宽泛的{ name: string; something: string; }。当你把这个变量传给组件时,TS只会做“结构兼容性”检查:只要变量包含目标类型的所有必填属性,就算有多余属性也会认为是兼容的,自然就不会报错了。
解决办法
如果想让变量也能触发严格检查,有两个简单的办法:
- 给变量显式指定目标类型:
这样TS在赋值的时候就会检查变量是否完全符合目标类型,多余属性直接就会报错。// 这里的FilterFormDefaultValues就是组件要求的defaultValues类型 const defaultVals: FilterFormDefaultValues = { name: "Alice", something: "oops" }; - 用
as const阻止类型拓宽:
不过这个办法会把所有属性变成只读的字面量类型,得确保组件的const defaultVals = { name: "Alice", something: "oops" } as const;defaultValues支持这种只读类型才行。
内容来源于stack exchange
相关产品推荐
相关产品推荐

