Выражение машинописного текста с нулевой отметкой, возможно, не определено, но только в угловом шаблоне

#angular #typescript

Вопрос:

У меня есть следующий код:

тс:

   get myArray(): any[]{
    return [1,2,3];
  }
 

шаблон:

 <p>Test:</p>
<div *ngIf="myArray?.length > 2">
  array has more than 2 items
</div>
 

Для этого компилятор сообщает мне:

 Error in src/app/app.component.html (2:13)
Object is possibly 'undefined'.
 

Почему? Код работает просто отлично, если я напишу точно такое же выражение в компоненте:

   constructor(){
    if(this.myArray?.length > 2){
      console.log("yay")
    }
  }
 

Пример стекблитца: https://stackblitz.com/edit/angular-ivy-hhpoag?file=src/app/app.component.ts

tsconfig:

 {
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "./",
    "outDir": "./dist/out-tsc",
    "strict": true,
    "suppressImplicitAnyIndexErrors": true,
    "sourceMap": true,
    "declaration": false,
    "downlevelIteration": true,
    "experimentalDecorators": true,
    "module": "esnext",
    "moduleResolution": "node",
    "importHelpers": true,
    "target": "es2015",
    "typeRoots": ["node_modules/@types"],
    "lib": ["es2018", "dom"]
  },
  "angularCompilerOptions": {
    "enableIvy": true,
    "fullTemplateTypeCheck": true,
    "strictInjectionParameters": true,
    "strictTemplates": true
  }
}
 

Комментарии:

1. Похоже, что в .html (в строгом режиме) не разрешается сравнивать значение null или undefined с числом, которое вы можете использовать *ngIf="myArray amp;amp; myArray.length>2" .ПРИМЕЧАНИЕ: работает *ngIf mtArray?.length , потому что это говорит «если существует, а не пусто».

2. Не знаю, почему он ведет себя по-другому, но в шаблоне ?. делает typeof myArray?.length number | undefined . В компоненте ? не имеет значения, потому что тип возвращаемого значения не может быть нулевым ( any[] ).

3. Удалить ? из *ngIf="myArray?.length > 2" ?

4. Почему вам нужно ?. всегда определенное значение?

5. Угловой шаблон не оставляет шансов. А также с асинхронным каналом и наблюдаемыми объектами — вам не будет разрешено сравнивать результат с числом способом < или>, потому что необязательный параметр не определен или равен нулю. Комментарий @Eliseo, вероятно, лучший вариант.

Ответ №1:

Один из моих коллег указал на источник ошибки:

Механизм угловых шаблонов (вероятно) затмевает тип моего геттера. myArray Тип будет изменен с any[] на any[] | undefined . Если мы это сделаем, код машинописи в компоненте также выйдет из строя:

 import { Component } from '@angular/core';
import { FormArray, FormControl, FormGroup } from '@angular/forms';

@Component({
  selector: 'my-app',
  template: ``
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {

  get myArray(): any[] | undefined {    // causes build time error too without a template
    return [1,2,3];
  }

  constructor(){
    if(this.myArray?.length > 2){
      console.log("yay")
    }
  }
}

 

Одно из возможных решений-проверить значение и при необходимости заменить его, как это показано в шаблоне:

 <p>Test:</p>
<div *ngIf="(myArray?.length ?? 0) > 2">
  array has more than 2 items
</div>
 

Стекблитц: https://stackblitz.com/edit/angular-ivy-muwdqu?file=src/app/app.component.html