我正在开发一个 Angular 16 项目,在该项目中我使用反应式声明方法。
经常,我必须处理发出不同类型数据的 Observables——要么是成功的数据,要么是错误的对象。两种返回类型都有其单独的接口。
我通常将它们定义为联合类型,但我发现在 Angular 模板中处理这些类型很麻烦。
这里有一个例子:
interface DataSuccess {
value: string;
}
interface DataError {
error: boolean;
message: string;
}
type DataOrError = DataSuccess | DataError | null;
在我的组件中,我有一个这种联合类型的 Observable:
// COMPONENT
data$: Observable<DataOrError> = this.myService.getData();
在我的 Angular 模板中,我想根据 data$ 发出 DataSuccess 对象还是 DataError 对象来显示不同的内容。但是,这会导致 TypeScript 错误,指出 DataSuccess 类型上不存在错误,DataError 类型上不存在值。
// TEMPLATE
<div *ngIf="data$ | async as data">
<!-- Throws TypeScript error -->
<div *ngIf="data?.error">{{ data.message }}</div>
<!-- Also throws TypeScript error -->
<div *ngIf="!data?.error">{{ data.value }}</div>
</div>
在 Angular 中处理这种情况的最佳实践是什么? 有没有一种方法可以在 Angular 模板中执行类型检查而无需求助于类型安全性较低的方法(例如使用 $any() 类型转换函数)或将逻辑移至组件文件? 是否有任何我可能忽略的 Angular 功能或 TypeScript 功能可以简化此操作?
我在这里看到了几个类似的问题,但它们很旧,答案很少,而且答案并不令人满意。我想知道现在情况是否有所改变。
作为替代方案,我考虑使用统一的模型,即不是将两种不同的类型放入一个联合中,而是像这样:
interface DataResponse {
value?: object;
error?: boolean;
message:? string;
}
这将解决我的模板推断问题,但是,我会失去一些类型安全性。这是处理此问题的明智方法还是会为将来可能出现的问题打开大门?
您可以定义一个如下所示的枚举,而不是创建不同的接口来描述数据的状态:
enum DataStatus {
Error = "Error",
Success = "Success",
}
您现在可以在 html 模板中检查数据状态:
// TEMPLATE
<div *ngIf="data$ | async as data">
<ng-container *ngIf="data.status === DataStatus.Success">
<div>{{ data.message }}</div>
<div>{{ data.value }}</div>
</ng-container>
</div>