javascript - 在开关中投射类型
问题描述
我正在尝试模块化我的类型转换。这是我的代码:
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 我要返回AbstractData
OR UserData
OR MachineData
OR 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 &
,但这没有任何意义。我以为如果我施放,我会返回什么就很清楚了,但我发现它不是那么简单。我错过了什么?
解决方案
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.
推荐阅读
- mariadb - MariaDB 服务可用性
- javascript - 如何通过单击一个页面上的按钮将按钮值存储到 sessionStorage 中并将其添加到另一页上的文本输入字段中?
- node.js - TypeORM 迁移未发现任何更改
- reactjs - 如何将 Redux 添加到具有身份验证的 React 应用程序?
- javascript - 在这种情况下如何避免嵌套承诺
- javascript - JavaScript:如何在功能后循环控制台日志和用户输入?
- c++ - 是否可以使用 C++ 中的私有返回类型在类外部定义函数?
- windows - 有谁知道如何使用 PS AppDeployToolkit 使用 slmgr /ipk?
- ansible - 如何在 Ubuntu 18.04 上完全删除 Ansible 2.8.3
- c++ - 带有类的 constexpr 关键字的问题