角度和异步管道打字稿抱怨 null

时间:2021-04-21 06:39:32

标签: angular ngrx

我有以下容器组件

export class EventsComponent {
  data$: Observable<Data[]> = this.store.select(data);
  loading$: Observable<boolean> = this.store.select(loading);
}

并通过 | async 将 observable 绑定到展示组件:

 <app-presentational 
   [rowData]="data$ | async" 
   [loading]="loading$ | async" 
   ...
export class PresentComponent {
  @Input()
  rowData: Data[];

  @Input()
  loading: boolean;
}

然而,TS 编译器总是抱怨异步管道可能返回 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;
}

4 个答案:

答案 0 :(得分:0)

仅凭您提供的信息我无法判断,但是当 Observable 未提供值时,组件看起来只需要空处理

<app-presentational 
  [rowData]="data$ | async" 
  [loading]="(loading$ | async) || false"
/>

答案 1 :(得分:0)

Angular 文档指出 here

<块引用>

上述问题有两种可能的解决方法:

在模板中,包含非空断言运算符!在末尾 可以为空的表达式,例如

在这个例子中,编译器忽略了类型不兼容 可空性,就像在 TypeScript 代码中一样。在异步的情况下 管道,注意表达式需要用括号括起来,如 在

完全禁用 Angular 模板中的严格空检查。

当启用strictTemplates时,仍然可以禁用 类型检查的某些方面。设置选项 strictNullInputTypes 到 false 禁用严格的空检查 角度模板。此标志适用于属于部分的所有组件 应用程序。

但是,您可以:

  1. 使用空合并运算符 (??) - 在 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>
  1. 使用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>

答案 2 :(得分:0)

修改您的代码片段,如下所示。应该修复空分配错误。

 <app-presentational 
   [rowData]="(data$ | async)!" 
   [loading]="(loading$ | async)!" 
   ...

答案 3 :(得分:-1)

您的 Store State 初始值未定义,这就是您获得 null 或未声明 Store State 对象的原因

  1. 尝试使用初始值:
export class PresentComponent {
  @Input()
  rowData: Data[] = [];

  @Input()
  loading = false;

同样,对于 .select,您正在选择它处理字符串的部分状态: 尝试将它们转换为字符串

export class EventsComponent {
  data$: Observable<Data[]> = this.store.select('data');
  loading$: Observable<boolean> = this.store.select('loading');

你也可以在进入 state 中的对象时使用多个。

this.store.select('name1', 'name2', ...)
  1. 但由于您的初始状态,它仍然可能为空。 您可以尝试不使用 |异步所以这永远不会为空
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;
    });
  }
}