首页 > 解决方案 > 打字稿编译器不强制泛型

问题描述

问题

我有一个减速器模型,其动作接受payload预期的形状{ id: string, newValues: Partial<A_or_B> }。在下面的代码中,A_or_B当我声明内联时不强制执行类型newValues;但是,如果我newValues提前声明并为其分配属性,则会强制执行约束。即使声明为内联,我如何才能强制执行约束?A_or_BnewValues

有问题的代码

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 链接在这里

标签: reactjstypescriptgenerics

解决方案


union这是大多数人在使用 typescript时遇到的常见问题。有些人将它们视为交集类型,而有些人希望它们表现得更像互斥类型。

但是,typescript 对联合类型有两种不同的解释,具体取决于您的用例。

特性

当您尝试访问联合类型的属性时,您只能访问联合的所有成员共有的属性。另一种说法是,您只能访问联合成员的属性的交集。

这可能是拗口,但打字稿文档给出了一个很好的类比来解释这一点:

例如,如果我们有一个房间里有戴帽子的高个子,而另一个房间里有讲西班牙语的人戴帽子,在组合这些房间后,我们对每个人的唯一了解就是他们必须戴帽子。

所以在属性访问的情况下,typescript 只允许访问属性的一个子集(没有来自用户的任何进一步提示),从而形成了一个交集。

成员资格(又名类型推断)

当涉及到类型推断时,编译器在允许匹配联合类型方面非常自由。从本质上讲,如果你想成为这个小组的一员,你只需要看起来像这个小组的成员之一。在这种情况下,您不必拥有与联合体的每个成员的属性相匹配的属性。


也许您的问题的解决方案是只使用交集类型x

const x: Partial<A&B> = {};
x.color = "red"; // works!

...
newValues: x; // also works

这解决了属性访问成员资格的问题


推荐阅读