TypeScript编译器未对联合类型Partial<A_or_B>的内联声明做类型校验
问题描述
我在reducer模型中定义了一个action,其接收的payload类型结构为{ id: string, newValues: Partial<A_or_B> }。实际开发中发现,当我内联声明newValues时,TypeScript不会对A_or_B的类型约束做校验;但如果我提前声明newValues变量再为其赋值属性,约束就可以正常生效。请问如何配置才能让内联声明的newValues也能正常触发A_or_B的类型约束校验?
问题代码
import { useContext } from "react"; import { AppDispatchContext } from "../src/AppProvider"; import { ActionTypes, A_or_B } from "./interfaces"; export default function App() { const dispatch = useContext(AppDispatchContext); const x: Partial<A_or_B> = {}; // 此处会抛出类型错误:Property 'color' does not exist on type // 'Partial<A> | Partial<B>'. // Property 'color' does not exist on type 'Partial<A>'. x.color = "red"; dispatch({ type: ActionTypes.POINT_UPDATED, // 此处仅内联声明newValues,color仅属于B类型,为什么不会触发类型错误? payload: { id: "x", newValues: { color: "red" } } }); }
原因说明
这个差异来自TypeScript联合类型的两种校验规则:
- 给联合类型赋值对象字面量时,TS只会校验该字面量是否符合联合中任意一个分支的类型要求,只要符合其中一个就判定为合法。你内联写的
{color: "red"}符合Partial<B>的要求,所以不会触发报错。 - 当你提前声明了类型为
Partial<A_or_B>的变量再修改属性时,TS无法确定这个变量当前属于联合的哪个分支,所以只允许操作所有分支共有的属性,因此给x.color赋值会抛出错误。
解决方案
根据你的实际需求选择对应方案:
- 如果你希望
newValues只能传入A和B两种类型的共有属性,直接修改action的payload类型定义,把Partial<A_or_B>替换为Partial<A & B>,这样只要传入任意非共有的属性,不管是内联写法还是提前声明变量,都会触发类型错误。 - 如果你允许传入单个分支的属性,只是希望内联写法也能提前识别不符合要求的字段:
- 给内联的
newValues显式标注类型,或者提前声明带类型的newValues变量再传入:
// 此处会直接抛出类型错误 const newValues: Partial<A_or_B> = { color: "red" }; dispatch({ type: ActionTypes.POINT_UPDATED, payload: { id: "x", newValues } });- 在
tsconfig.json中开启更严格的校验配置,提升类型检查的严格度:
{ "compilerOptions": { "strict": true, "exactOptionalPropertyTypes": true, "noImplicitAny": true } } - 给内联的
内容的提问来源于stack exchange,提问作者RouteMapper
相关产品推荐
相关产品推荐

