打字稿无法理解“一种类型”中的对象键

时间:2020-01-13 18:41:14

标签: typescript

我有一些类似的功能:

actions.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>;

reducer.ts

import { Action } from './actions';
import { State } from './state';

export default (state: State, action: Action): State => {
  switch (action.type) {
    case 'ADD_TO_CART': {
      return [...state, action.id];
    }
    case 'EMPTY_CART': {
      return [];
    }
    case 'REMOVE_FROM_CART': {
      return state.filter(id => id !== action.id);
    }
    default:
      return state;
  }
};

我的IDE告诉我类型Action是:

type Action = {
    id: string;
    type: string;
} | {
    type: string;
} | {
    id: string;
    type: string;
}

但是,action.idreducer.ts的两种情况都引发此Typescript错误:

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

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

2 个答案:

答案 0 :(得分:4)

您已经创建了一个潜在的discriminated union type Action,但是您的判别式属性type扩展为string类型-这就是TS无法查明的原因,你的意思是工会的一部分。

一个简单的解决方法是使用as const注释动作创建者函数的返回类型,因此保留字符串type的文字类型:

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

// do this for the other functions as well

Playground

答案 1 :(得分:0)

对福特出色答案的补充

从对问题的评论中:

只是看了看您的链接,我不确定示例在做什么,我的代码没有做

您的问题是,您在欺骗联合中的类型:您期望推理引擎过多。您需要使用typeinterface而不是(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!
    }
}

playground