angular 和异步管道打字稿抱怨 null
angular and async pipe typescript complains for null
我有以下容器组件
export class EventsComponent {
data$: Observable<Data[]> = this.store.select(data);
loading$: Observable<boolean> = this.store.select(loading);
}
并通过 | async
将可观察对象绑定到展示组件:
<app-presentational
[rowData]="data$ | async"
[loading]="loading$ | async"
...
export class PresentComponent {
@Input()
rowData: Data[];
@Input()
loading: boolean;
}
然而,TS 编译器总是抱怨异步管道可能 return null。
更新,这是我得到的确切错误
Type 'boolean | null' is not assignable to type 'boolean'.
Type 'null' is not assignable to type 'boolean'.ngtsc(2322)
所以我真的必须把我所有的 @Input()
都改成这个吗?
export class PresentComponent {
@Input()
rowData: Data[] | null;
@Input()
loading: boolean | null;
}
你的 Store State 初始化是未定义的,这就是你得到 null 或你没有声明 Store State 对象的原因
- 尝试使用初始值:
export class PresentComponent {
@Input()
rowData: Data[] = [];
@Input()
loading = false;
同样对于 .select 你是 selecting 状态的一部分,它与字符串一起工作:
尝试将它们转换为字符串
export class EventsComponent {
data$: Observable<Data[]> = this.store.select('data');
loading$: Observable<boolean> = this.store.select('loading');
进入状态中的对象内部时,您也可以使用倍数。
this.store.select('name1', 'name2', ...)
- 但它仍然可能是空的,因为你的初始状态。
您可以尝试不使用 |异步所以这永远不会是 null
export class EventsComponent implements OnInit {
data: Data[] = [];
loading = false;
constructor(private store: Store<{ data: Data[], loading: boolean}>) {
}
ngOnInit(): void {
// you can do one by one
this.store.select('data')
.subscribe(next => this.data = next);
this.store.select('loading')
.subscribe(next => this.loading = next);
// or do
// all together
this.store.subscribe(next => {
this.data = next.data;
this.loading = next.loading;
});
}
}
我无法仅根据您提供的信息判断,但看起来组件只需要在 Observable 未提供值时进行空处理
<app-presentational
[rowData]="data$ | async"
[loading]="(loading$ | async) || false"
/>
作为 Angular 文档点 here:
There are two potential workarounds to the above issues:
In the template, include the non-null assertion operator ! at the end
of a nullable expression, such as <user-detail [user]="user!" />.
In this example, the compiler disregards type incompatibilities in
nullability, just as in TypeScript code. In the case of the async
pipe, note that the expression needs to be wrapped in parentheses, as
in <user-detail [user]="(user$ | async)!" />.
Disable strict null checks in Angular templates completely.
When strictTemplates is enabled, it is still possible to disable
certain aspects of type checking. Setting the option
strictNullInputTypes to false disables strict null checks within
Angular templates. This flag applies for all components that are part
of the application.
但是,您可以:
而不是使用非空断言运算符甚至禁用 Angular 严格检查
- 使用无效合并运算符 (
??
) - 在 Angular 12+: 中可用
TS:
@Component({
template: ``,
})
export class PresentationalComponent {
@Input() loading: boolean;
@Input() rowData: Data[];
}
HTML:
<app-presentational
[loading]="(loading$ | async) ?? false"
[rowData]="(rowData$ | async) ?? []"
></app-presentational>
- 使用
ngAcceptInputType_*
:
TS:
@Component({
template: ``,
})
export class PresentationalComponent {
static ngAcceptInputType_loading?: boolean | null;
// Note that if you have `@angular/cdk` installed you can use this instead:
// static ngAcceptInputType_loading: BooleanInput;
static ngAcceptInputType_rowData?: Data[] | null;
@Input() loading: boolean;
@Input() rowData: Data[];
}
HTML:
<app-presentational
[rowData]="rowData$ | async"
[loading]="loading$ | async"
></app-presentational>
- TS 4.3+:
getter
和 setter
的不同类型:
TS:
@Component({
template: ``,
})
export class PresentationalComponent {
@Input()
// Note that if you have `@angular/cdk` installed you can use `BooleanInput` instead.
set loading(loading: boolean | null | undefined) {
this._loading = loading ?? false;
}
get loading(): boolean {
return this._loading;
}
private _loading: Data[];
@Input()
set rowData(rowData: Data[] | null | undefined) {
this.rowData = rowData ?? [];
}
get rowData(): Data[] {
return this._rowData;
}
private _rowData: Data[] = [];
}
请注意,现在您应该更喜欢使用选项 3 而不是选项 2,因为 input setter coercion fields
are being deprecated。
按如下方式修改您的代码段。应该修复空赋值错误。
<app-presentational
[rowData]="(data$ | async)!"
[loading]="(loading$ | async)!"
...
我有以下容器组件
export class EventsComponent {
data$: Observable<Data[]> = this.store.select(data);
loading$: Observable<boolean> = this.store.select(loading);
}
并通过 | async
将可观察对象绑定到展示组件:
<app-presentational
[rowData]="data$ | async"
[loading]="loading$ | async"
...
export class PresentComponent {
@Input()
rowData: Data[];
@Input()
loading: boolean;
}
然而,TS 编译器总是抱怨异步管道可能 return null。
更新,这是我得到的确切错误
Type 'boolean | null' is not assignable to type 'boolean'.
Type 'null' is not assignable to type 'boolean'.ngtsc(2322)
所以我真的必须把我所有的 @Input()
都改成这个吗?
export class PresentComponent {
@Input()
rowData: Data[] | null;
@Input()
loading: boolean | null;
}
你的 Store State 初始化是未定义的,这就是你得到 null 或你没有声明 Store State 对象的原因
- 尝试使用初始值:
export class PresentComponent {
@Input()
rowData: Data[] = [];
@Input()
loading = false;
同样对于 .select 你是 selecting 状态的一部分,它与字符串一起工作: 尝试将它们转换为字符串
export class EventsComponent {
data$: Observable<Data[]> = this.store.select('data');
loading$: Observable<boolean> = this.store.select('loading');
进入状态中的对象内部时,您也可以使用倍数。
this.store.select('name1', 'name2', ...)
- 但它仍然可能是空的,因为你的初始状态。 您可以尝试不使用 |异步所以这永远不会是 null
export class EventsComponent implements OnInit {
data: Data[] = [];
loading = false;
constructor(private store: Store<{ data: Data[], loading: boolean}>) {
}
ngOnInit(): void {
// you can do one by one
this.store.select('data')
.subscribe(next => this.data = next);
this.store.select('loading')
.subscribe(next => this.loading = next);
// or do
// all together
this.store.subscribe(next => {
this.data = next.data;
this.loading = next.loading;
});
}
}
我无法仅根据您提供的信息判断,但看起来组件只需要在 Observable 未提供值时进行空处理
<app-presentational
[rowData]="data$ | async"
[loading]="(loading$ | async) || false"
/>
作为 Angular 文档点 here:
There are two potential workarounds to the above issues:
In the template, include the non-null assertion operator ! at the end of a nullable expression, such as <user-detail [user]="user!" />.
In this example, the compiler disregards type incompatibilities in nullability, just as in TypeScript code. In the case of the async pipe, note that the expression needs to be wrapped in parentheses, as in <user-detail [user]="(user$ | async)!" />.
Disable strict null checks in Angular templates completely.
When strictTemplates is enabled, it is still possible to disable certain aspects of type checking. Setting the option strictNullInputTypes to false disables strict null checks within Angular templates. This flag applies for all components that are part of the application.
但是,您可以:
而不是使用非空断言运算符甚至禁用 Angular 严格检查- 使用无效合并运算符 (
??
) - 在 Angular 12+: 中可用
TS:
@Component({
template: ``,
})
export class PresentationalComponent {
@Input() loading: boolean;
@Input() rowData: Data[];
}
HTML:
<app-presentational
[loading]="(loading$ | async) ?? false"
[rowData]="(rowData$ | async) ?? []"
></app-presentational>
- 使用
ngAcceptInputType_*
:
TS:
@Component({
template: ``,
})
export class PresentationalComponent {
static ngAcceptInputType_loading?: boolean | null;
// Note that if you have `@angular/cdk` installed you can use this instead:
// static ngAcceptInputType_loading: BooleanInput;
static ngAcceptInputType_rowData?: Data[] | null;
@Input() loading: boolean;
@Input() rowData: Data[];
}
HTML:
<app-presentational
[rowData]="rowData$ | async"
[loading]="loading$ | async"
></app-presentational>
- TS 4.3+:
getter
和setter
的不同类型:
TS:
@Component({
template: ``,
})
export class PresentationalComponent {
@Input()
// Note that if you have `@angular/cdk` installed you can use `BooleanInput` instead.
set loading(loading: boolean | null | undefined) {
this._loading = loading ?? false;
}
get loading(): boolean {
return this._loading;
}
private _loading: Data[];
@Input()
set rowData(rowData: Data[] | null | undefined) {
this.rowData = rowData ?? [];
}
get rowData(): Data[] {
return this._rowData;
}
private _rowData: Data[] = [];
}
请注意,现在您应该更喜欢使用选项 3 而不是选项 2,因为 input setter coercion fields
are being deprecated。
按如下方式修改您的代码段。应该修复空赋值错误。
<app-presentational
[rowData]="(data$ | async)!"
[loading]="(loading$ | async)!"
...