为什么类型在枚举中没有重叠



我试图弄清楚为什么TypeScript报告我的条件总是错误的,因为在这种情况下Action.UP | Action.DOWNAction.LEFT之间没有类型重叠(游乐场链接):

class Component<S> {
    public state: S;
    public render() {}
}
enum Action {
    UP,
    DOWN,
    LEFT,
    RIGHT,
}
interface State {
    action: Action;
}
const initialAction: Action.UP | Action.DOWN = Action.UP;
class MyComponent extends Component<State> {
    public state = {
        action: initialAction,
    }
    public render() {
        // Why is action not of type Action as declared in the interface?
        const isLateral = this.state.action === Action.LEFT;
    }
}

如果this.state.action只有 Action.UP | Action.DOWN 类型的初始值,但在接口中声明为 Action 类型,为什么我不能将其与 Action.LEFT 进行比较?如果我将来可以将this.state.action重新分配为 LEFTRIGHT,为什么条件总是假的?

回答"为什么?

为什么操作不是接口中声明的 Action 类型?

它属于不同的类型,因为子类正在重新定义 state 属性,并为其提供比父类更窄的类型。如果您通过设计这样做,那么您可以通过在 render() 中强制转换来访问父类的更广泛的接口。

const isLateral = (this as Component<State>).state.action === Action.LEFT;

推荐的方法

或者,按照 React 组件文档所说的操作:

。如果您的组件需要使用本地状态,请直接在构造函数中将初始状态分配给 this.state:

也就是说,不要重新定义父类的状态属性;而是使用 extend 提供的已定义的 state 属性。在构造函数中设置其初始值。

class MyComponent extends Component<State> {
    constructor() { 
        super();
        this.state = {
            action: initialAction,
        }
    }
    public render() {
        const isLateral = this.state.action === Action.LEFT;
    }
}

您必须像这样键入公共状态:

public state: State = {
    action: initialAction,
}

否则 Typescript 会推断出state.actioninitialAction 的类型相同。

回答您评论中的问题

(游乐场链接)

在设置为新属性时,重新定义了子类中state的值和类型。

我的链接说明了这一点。我在父类中添加了一个名为 count 的新属性,类型为 number 。如果我在我的子类中将其定义为新属性,它会将其推断为 any ,因此可以在 render() 中设置为字符串。

但是,您可以看到我如何处理您原来的state财产。为了使用父级的状态类型,可以在构造函数中调用super(),然后定义this.state.action = initialAction;

这样,当您调用render()时,它将在this.state.action上查找Action类型,而不是新定义的Action.UP | Action.DOWN

在我们的

例子中,我们忘记了{} const A: React.FC<IProps> = (first, second, ...rest)因为必须const A: React.FC<IProps> = ({first, second, ...rest})。这太糟糕:)

最新更新