打字稿歧视联合类型安全不适用于子对象?
Typescript Discriminated Unions typesafety not working on child object?
我正在使用 Typescript 4 尝试创建一个带有 属性 的对象,该对象使用区分联合,但类型安全似乎不起作用?
export enum StageType {
PULL = 'pull',
FILTER = 'filter',
}
export enum StageMetricProperty {
IMPORTED = 'imported',
SKIPPED = 'skipped',
PIPED = 'piped',
ERRORS = 'errors',
PROCESSED = 'processed',
SENT = 'sent',
SAVED = 'saved',
}
// Pull stage metrics
export interface PullMetrics {
[StageMetricProperty.IMPORTED]?: number;
[StageMetricProperty.PIPED]?: number;
[StageMetricProperty.ERRORS]?: number;
}
export interface PullReportStage {
type: StageType.PULL;
name: string;
args: string[];
status: StageStatus;
errors: string[];
metrics: PullMetrics;
}
// Filter Stage Metrics
export interface FilterMetrics {
[StageMetricProperty.SKIPPED]?: number;
[StageMetricProperty.PIPED]?: number;
[StageMetricProperty.ERRORS]?: number;
}
export interface FilterReportStage {
type: StageType.FILTER;
name: string;
args: string[];
status: StageStatus;
errors: string[];
metrics: FilterMetrics;
}
export type ReportStage =
| PullReportStage
| FilterReportStage;
根据上面的定义,我尝试创建我的 FilterReportStage 对象(如下),但是 Typescript 从不报告 FilterReportStage.metrics
属性 中对象的任何错误,尽管它确实在顶部正确报告了错误级别 metric: FilterMetrics
对象?
const metric: FilterMetrics = {
[StageMetricProperty.IMPORTED]: 123, // <-- Correctly parsed as invalid (as expected).
[StageMetricProperty.PIPED]: 123, // <-- Valid
};
const sample = {
type: StageType.FILTER,
name: 'utils:command',
args: [],
errors: [],
metrics: {
[StageMetricProperty.IMPORTED]: 123, // <-- Invalid, Typescript does not report aby errors.
[StageMetricProperty.PIPED]: 123, // <-- Valid
} as FilterMetrics,
status: StageStatus.PENDING
} as FilterReportStage;
有谁能指导我为什么会发生这种情况?
当你使用 type assertions(例如,as FilterMetrics
)时,你是在告诉打字稿“我比你知道的多,所以不要在这里检查我的工作。假设它是类型我说是”。所以既然你告诉打字稿不要检查你的工作,它就不会。
如果你想要类型检查,那么使用标准类型(例如,: FilterReportStage
),而不是类型断言:
const sample: FilterReportStage = {
type: StageType.FILTER,
name: 'utils:command',
args: [],
errors: [],
metrics: {
[StageMetricProperty.IMPORTED]: 123, // <--- it points out the error here
[StageMetricProperty.PIPED]: 123,
},
status: StageStatus.PENDING
};
我正在使用 Typescript 4 尝试创建一个带有 属性 的对象,该对象使用区分联合,但类型安全似乎不起作用?
export enum StageType {
PULL = 'pull',
FILTER = 'filter',
}
export enum StageMetricProperty {
IMPORTED = 'imported',
SKIPPED = 'skipped',
PIPED = 'piped',
ERRORS = 'errors',
PROCESSED = 'processed',
SENT = 'sent',
SAVED = 'saved',
}
// Pull stage metrics
export interface PullMetrics {
[StageMetricProperty.IMPORTED]?: number;
[StageMetricProperty.PIPED]?: number;
[StageMetricProperty.ERRORS]?: number;
}
export interface PullReportStage {
type: StageType.PULL;
name: string;
args: string[];
status: StageStatus;
errors: string[];
metrics: PullMetrics;
}
// Filter Stage Metrics
export interface FilterMetrics {
[StageMetricProperty.SKIPPED]?: number;
[StageMetricProperty.PIPED]?: number;
[StageMetricProperty.ERRORS]?: number;
}
export interface FilterReportStage {
type: StageType.FILTER;
name: string;
args: string[];
status: StageStatus;
errors: string[];
metrics: FilterMetrics;
}
export type ReportStage =
| PullReportStage
| FilterReportStage;
根据上面的定义,我尝试创建我的 FilterReportStage 对象(如下),但是 Typescript 从不报告 FilterReportStage.metrics
属性 中对象的任何错误,尽管它确实在顶部正确报告了错误级别 metric: FilterMetrics
对象?
const metric: FilterMetrics = {
[StageMetricProperty.IMPORTED]: 123, // <-- Correctly parsed as invalid (as expected).
[StageMetricProperty.PIPED]: 123, // <-- Valid
};
const sample = {
type: StageType.FILTER,
name: 'utils:command',
args: [],
errors: [],
metrics: {
[StageMetricProperty.IMPORTED]: 123, // <-- Invalid, Typescript does not report aby errors.
[StageMetricProperty.PIPED]: 123, // <-- Valid
} as FilterMetrics,
status: StageStatus.PENDING
} as FilterReportStage;
有谁能指导我为什么会发生这种情况?
当你使用 type assertions(例如,as FilterMetrics
)时,你是在告诉打字稿“我比你知道的多,所以不要在这里检查我的工作。假设它是类型我说是”。所以既然你告诉打字稿不要检查你的工作,它就不会。
如果你想要类型检查,那么使用标准类型(例如,: FilterReportStage
),而不是类型断言:
const sample: FilterReportStage = {
type: StageType.FILTER,
name: 'utils:command',
args: [],
errors: [],
metrics: {
[StageMetricProperty.IMPORTED]: 123, // <--- it points out the error here
[StageMetricProperty.PIPED]: 123,
},
status: StageStatus.PENDING
};