问题
我有一个 reducer 模型,其操作接受 payload
预计形状为{ id: string, newValues: Partial<A_or_B> }
。在下面的代码中,强制执行类型 A_or_B
当我声明 newValues
时,不强制执行排队;但是,如果我声明 newValues
提前并为其分配属性,强制执行约束。 如何强制执行 A_or_B
上的约束即使newValues
是否声明为内联?
有问题的代码
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,
// why can I assign a color to Partial<A>|Partial<B> if 'color'
// only exists on B?
payload: { id: "x", newValues: { color: "red" } }
});
}
CodeSandbox 链接
最佳答案
这是大多数人遇到的常见问题 union
在 typescript 中输入。有些人将它们视为交集类型,而有些人希望它们的行为更像互斥类型。
但是,TypeScript 对联合类型有两种不同的解释,具体取决于您的用例。
属性
当您尝试访问联合类型的属性时,您只能访问联合所有成员共同的属性。另一种说法是,您只能访问联合成员属性的交集。
这可能有点拗口,但 typescript 文档给出了一个很好的 analogy解释一下:
For example, if we had a room of tall people wearing hats, and another room of Spanish speakers wearing hats, after combining those rooms, the only thing we know about every person is that they must be wearing a hat.
因此,在属性访问的情况下,TypeScript 仅允许访问属性的子集(无需用户提供任何进一步的提示),从而形成交集。
成员资格(又名类型推断)
在类型推断方面,编译器对于允许匹配联合类型的内容相当自由。本质上它是说,如果你想成为这个群体的一员,你只需看起来像这个群体的成员之一。在这种情况下,您不必拥有与联合体每个成员的属性相匹配的属性。
也许问题的解决方案是仅使用 x
的交集类型:
const x: Partial<A&B> = {};
x.color = "red"; // works!
...
newValues: x; // also works
这解决了属性(property)访问和成员身份的问题
关于reactjs - Typescript 编译器不强制执行泛型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69330740/