提问人:MikhailRatner 提问时间:9/2/2023 更新时间:9/3/2023 访问量:91
在 Angular 16 模板/类型推断中处理联合类型的最干净方法?
Cleanest way to handle Union Types in Angular 16 Templates / Type inference?
问:
我正在做一个 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;
}
这将解决我的模板推理问题,但是,我会失去一些类型安全性。这是处理此问题的可取方法,还是会为将来可能出现的问题打开大门?
答:
在这里,我创建了一个堆栈闪电战 https://stackblitz.com/edit/stackblitz-starters-9vxc5l?file=src%2Ftest.service.ts
在此,我在您的两个响应中创建了一个名为 type 的新值
interface DataSuccess {
type: ResponseType.success;
value: string;
}
interface DataError {
type: ResponseType.error;
error: boolean;
message: string;
}
enum ResponseType {
success,
error,
}
并根据类型将订阅的结果分配给对象。 我认为当您为单个 Observable 提供多种类型时,这将是一种可接受且干净的方式。 此方法使代码的类型更加安全。
评论
error: boolean
interface DataResponse<T> { success: T | null; error: ErrorResponse | null }
interface BaseResponse { success: boolean; errors: Error[]; stackTrace : StackTrace[], info:string }
评论