Typescript不理解'中的对象键;一种为'型;

Typescript不理解'中的对象键;一种为'型;,typescript,Typescript,我有这样一些功能: 动作。ts export const addToCart = (id: string) => ({ id, type: 'ADD_TO_CART', }); export const emptyCart = () => ({ type: 'EMPTY_CART', }); export const removeFromCart = (id: string) => ({ id, type: 'REMOVE_FROM_CART', });

我有这样一些功能:

动作。ts

export const addToCart = (id: string) => ({
  id,
  type: 'ADD_TO_CART',
});

export const emptyCart = () => ({
  type: 'EMPTY_CART',
});

export const removeFromCart = (id: string) => ({
  id,
  type: 'REMOVE_FROM_CART',
});

export type Action =
  | ReturnType<typeof addToCart>
  | ReturnType<typeof emptyCart>
  | ReturnType<typeof removeFromCart>;
我的IDE告诉我动作的类型是:

type Action = {
    id: string;
    type: string;
} | {
    type: string;
} | {
    id: string;
    type: string;
}
但是,
reducer.ts
中的
action.id
两种情况都会引发此类型脚本错误:

Property 'id' does not exist on type 'Action'.
  Property 'id' does not exist on type '{ type: string; }'.

这里有什么问题?我的类型似乎正确,并且我正在使用其中一个类型选项中存在的一个对象键。

您已经创建了一个潜在的
操作
,但是您的判别属性
类型
被扩展为
字符串
类型-这就是TS无法找到您所指的联合部分的原因

一个简单的修复方法是使用注释action creator函数的返回类型,因此保留
type
的字符串文本类型:

export const addToCart = (id: string) => ({
  id,
  type: 'ADD_TO_CART',
}) as const; // add `as const`

// do this for the other functions as well

福特优秀答案的补充

根据对该问题的评论:

只是看了一下你的链接,我不确定我的代码没有做什么,示例是这样的

你的问题是你在欺骗你的工会成员:你对推理机的期望有点过高。您需要使用
type
interface
而不是(ab)使用
ReturnType
显式键入减速器操作,一切都会很好:

type AddToCart = {
    type: 'ADD_TO_CART',
    id: string,
};

type EmptyCart = {
    type: 'EMPTY_CART'
};

type ReducerAction = AddToCart | EmptyCart;

const reducer = (state: any, action: ReducerAction) => {
    switch (action.type) {
        case 'ADD_TO_CART': console.log(action.id); // ok!
        case 'EMPTY_CART': console.log(action.id);  // compiler error!
    }
}

您有一个类型,它是三个子类型的并集。在您缩小类型范围之前,它必须像它们中的任何一个一样工作,并且它们并不都具有
id
属性。你可能想要一个@JaredSmith,这是有道理的。我问题中的代码来自我的React-context方法(使用操作和Redux之类的缩减器)。在使用Typescript时如何处理这个问题?刚刚编辑了我的评论。您可能想要一个有差别的联合,在这里您可以
切换
。我一直在使用它来执行减速机操作。@JaredSmith刚刚查看了您的链接,我不确定我的代码没有执行示例中的操作。你能举个例子来回答吗?
type AddToCart = {
    type: 'ADD_TO_CART',
    id: string,
};

type EmptyCart = {
    type: 'EMPTY_CART'
};

type ReducerAction = AddToCart | EmptyCart;

const reducer = (state: any, action: ReducerAction) => {
    switch (action.type) {
        case 'ADD_TO_CART': console.log(action.id); // ok!
        case 'EMPTY_CART': console.log(action.id);  // compiler error!
    }
}