首页 > 解决方案 > 在开关中投射类型

问题描述

我正在尝试模块化我的类型转换。这是我的代码:

export enum detailsDataTypes {
  MACHINE = 'MACHINE',
  USER = 'USER',
  ABSTRACT = 'ABSTRACT',
}

export type sharedTypes = {
  name?: string;
  OEECategory?: string;
  OAECategory?: string;
  color?: string;
  type?: detailsDataTypes;
};

export type AbstractData = sharedTypes & {
  layer: string;
};

export type UserData = sharedTypes & {
  timeout: number;
  stateAfterTimeout: string;
  accessCanChoose: string;
  accessCanOverride: string;
};

export type MachineData = sharedTypes & {
  stateCategory: string;
  timeout: number;
  stateAfterTimeout: string;
  accessCanChoose: string;
  accessCanOverride: string;
  canOverrideOnlyByStates: boolean;
};

type DetailsData = AbstractData | UserData | MachineData;

export const detailsDataCaster = (data: DetailsData): DetailsData | null => {
  switch (data.type) {
    case detailsDataTypes.ABSTRACT:
      return <AbstractData>data;
    case detailsDataTypes.MACHINE:
      return <MachineData>data;
    case detailsDataTypes.USER:
      return <UserData>data;
    default:
      console.log('Wrong data type. Go yell at backend team or check your mocks');
      return null;
  }
};

我想要实现的是告诉 TS 我要返回AbstractDataOR UserDataOR MachineDataOR null。但是现在,它不喜欢我这样做:

export const Details: FC<IDetails> = ({ data: $data = mockUserData }): ReactElement => {
  const data = detailsDataCaster($data);
  switch (data.type) {
    case detailsDataTypes.ABSTRACT:
      return <>Abstract</>;
    case detailsDataTypes.MACHINE:
      return <>Machine</>;
    case detailsDataTypes.USER:
      return <UserDisplay data={data} />; // error is here
    default:
      return <div />;
  }
};

错误

Type 'DetailsData' is not assignable to type 'UserData'.
  Type 'AbstractData' is not assignable to type 'UserData'.
    Type 'AbstractData' is missing the following properties from type '{ timeout: number; stateAfterTimeout: string; accessCanChoose: string; accessCanOverride: string; }': timeout, stateAfterTimeout, accessCanChoose, accessCanOverride

据我了解|,在 TS 中并不意味着 OR。我知道有 AND &,但这没有任何意义。我以为如果我施放,我会返回什么就很清楚了,但我发现它不是那么简单。我错过了什么?

标签: javascriptreactjstypescripttypes

解决方案


If every type extending the sahredTypes would specify its own type the switch will magically work:

export enum detailsDataTypes {
  MACHINE = 'MACHINE',
  USER = 'USER',
  ABSTRACT = 'ABSTRACT',
}

export interface sharedTypes {
  name?: string;
  OEECategory?: string;
  OAECategory?: string;
  color?: string;
  type?: detailsDataTypes;
};

export interface AbstractData extends sharedTypes {
  type: detailsDataTypes.ABSTRACT;

  layer: string;
};

export interface UserData extends sharedTypes {
  type: detailsDataTypes.USER;

  timeout: number;
  stateAfterTimeout: string;
  accessCanChoose: string;
  accessCanOverride: string;
};

export interface MachineData extends sharedTypes {
  type: detailsDataTypes.MACHINE;

  stateCategory: string;
  timeout: number;
  stateAfterTimeout: string;
  accessCanChoose: string;
  accessCanOverride: string;
  canOverrideOnlyByStates: boolean;
};

type DetailsData = AbstractData | UserData | MachineData;

Playgound link that shows the type is correctly inferred from the switch.


推荐阅读