в моем приложении Angular у меня есть компонент:

import { MakeService } from './../../services/make.service';
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-vehicle-form',
  templateUrl: './vehicle-form.component.html',
  styleUrls: ['./vehicle-form.component.css']
})
export class VehicleFormComponent implements OnInit {
  makes: any[];
  vehicle = {};

  constructor(private makeService: MakeService) { }

  ngOnInit() {
    this.makeService.getMakes().subscribe(makes => { this.makes = makes
      console.log("MAKES", this.makes);
    });
  }

  onMakeChange(){
    console.log("VEHICLE", this.vehicle);
  }
}

но в свойстве "делает" у меня ошибка. Не знаю, что с этим делать ...

mistake

Ответы (22)

Думаю, вы используете последнюю версию TypeScript. См. Раздел «Строгая инициализация класса» по ссылке .

Есть два способа исправить это:

А. Если вы используете VSCode, вам необходимо изменить версию TS, которую использует редактор.

Б. Просто инициализируйте массив, когда вы объявляете его внутри конструктора,

makes: any[] = [];

constructor(private makeService: MakeService) { 
   // Initialization inside the constructor
   this.makes = [];
}

Перейдите в свой файл tsconfig.json и измените свойство:

 "noImplicitReturns": false

, а затем добавьте

 "strictPropertyInitialization": false

в свойстве compilerOptions.

Ваш файл tsconfig.json должен выглядеть так:


{
      ...
      "compilerOptions": {
            ....
            "noImplicitReturns": ложь,
            ....
            "strictPropertyInitialization": false
      },
      "angularCompilerOptions": {
         ......
      }
 }

Надеюсь, это поможет !!

Удачи

Обновление на 2021 год:

есть свойство типа "strictPropertyInitialization"

Просто зайдите в tsconfig.json и установите

"строгий": ложь

, чтобы избавиться от ошибки компиляции.

В противном случае вам нужно инициализировать все ваши переменные, что немного раздражает.

причина этой ошибки:

  • машинописный текст - это своего рода более безопасный язык по сравнению с javascript.
  • , хотя эта безопасность повышена за счет включения strict. Таким образом, каждый раз, когда вы инициализируете переменную, машинописный текст хочет, чтобы они присвоили значение.

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

У вас есть 2 варианта (вместо отключения причины машинописного текста для существующих ...):

1. В вашем случае лучше всего набрать , что делает возможно неопределенным.

makes?: any[]
// or
makes: any[] | undefined

Таким образом, компилятор будет сообщать вам, когда вы попытаетесь получить доступ к , сделает, что он может быть неопределенным. В противном случае, если приведенные ниже строки // <- Не в порядке были выполнены до завершения getMakes или если getMakes завершился неудачно, ваше приложение выйдет из строя и возникнет ошибка времени выполнения. быть брошенным. Это определенно не то, что вам нужно.

makes[0] // <-- Not ok
makes.map(...) // <-- Not ok

if (makes) makes[0] // <-- Ok
makes?.[0] // <-- Ok
(makes ?? []).map(...) // <-- Ok

2. Вы можете предположить, что он никогда не выйдет из строя и что вы никогда не попытаетесь получить к нему доступ до инициализации, написав приведенный ниже код (рискованно!). Так что компилятор не позаботится об этом.

makes!: any[] 

Мы можем получить сообщение Свойство не имеет инициализатора и не определенно назначено в конструкторе при добавлении некоторой конфигурации в файл tsconfig.json, чтобы скомпилировать проект Angular в строгом режиме:

"compilerOptions": {
  "strict": true,
  "noImplicitAny": true,
  "noImplicitThis": true,
  "alwaysStrict": true,
  "strictNullChecks": true,
  "strictFunctionTypes": true,
  "strictPropertyInitialization": true,

Действительно, компилятор затем жалуется, что переменная-член не определена перед использованием.

В качестве примера переменной-члена, которая не определена во время компиляции, переменная-член, имеющая директиву @ Input:

@Input() userId: string;

Мы могли бы заставить компилятор замолчать, указав, что переменная может быть необязательной:

@Input() userId?: string;

Но тогда нам придется иметь дело со случаем, когда переменная не определена, и загромождать исходный код некоторыми такими операторами:

if (this.userId) {
} else {
}

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

Чтобы сообщить об этом компилятору, нужно добавить ! утверждение определенного присваивания оператор, например:

@Input() userId!: string;

Теперь компилятор понимает, что эта переменная, хотя и не определена во время компиляции, должна быть определена во время выполнения и во время, прежде чем она будет использована.

Теперь приложение должно убедиться, что эта переменная определена перед использованием.

В качестве дополнительной защиты мы можем утверждать, что переменная определяется, прежде чем использовать ее.

Мы можем утверждать, что переменная определена, то есть требуемая привязка ввода была фактически предоставлена ​​вызывающим контекстом:

private assertInputsProvided(): void {
  if (!this.userId) {
    throw (new Error("The required input [userId] was not provided"));
  }
}

public ngOnInit(): void {
  // Ensure the input bindings are actually provided at run-time
  this.assertInputsProvided();
}

Зная, что переменная была определена, теперь можно использовать переменную:

ngOnChanges() {
  this.userService.get(this.userId)
    .subscribe(user => {
      this.update(user.confirmedEmail);
    });
}

Обратите внимание, что метод ngOnInit вызывается после попытки привязки ввода, даже если привязкам не был предоставлен фактический ввод.

В то время как метод ngOnChanges вызывается после попытки привязки ввода и только в том случае, если привязкам был предоставлен фактический ввод.

замените

fieldname?: any[]; 

на это:

fieldname?: any; 

Разве вы не можете просто использовать утверждение с определенным назначением? (См. https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#definite-assignment-assertions)

т.е. объявление свойства как делает !: any [];! гарантирует, что машинописный текст определенно будет иметь значение во время выполнения.

Извините, я не пробовал это в angular, но у меня это отлично сработало, когда у меня была точно такая же проблема в React.

Получите эту ошибку во время добавления узла в мой проект Angular -

TSError:? Невозможно скомпилировать TypeScript: (путь) /base.api.ts:19:13 - ошибка TS2564: свойство 'apiRoot Path 'не имеет инициализатора и точно не назначается в конструкторе.

частный apiRootPath: string;

Solution -

Добавлено "strictPropertyInitialization": false в 'compilerOptions' из tsconfig.json.

мой package.json -

"dependencies": {
    ...
    "@angular/common": "~10.1.3",
    "@types/express": "^4.17.9",
    "express": "^4.17.1",
    ...
}

Ссылочный URL - https://www.ryadel.com/en/ts2564-ts-property-has-no-initializer-typescript-error-fix-visual-studio-2017-vs2017/

Комментарий к строке // "strict": true в файле tsconfig.json.

Рядом с переменными "?" Исправить можно, поставив.

Пример:

---------> id?: Число ---------> имя?: строка

If you want to initialize an object based on an interface you can initialize it empty with following statement.

myObj: IMyObject = {} as IMyObject;

Это обсуждалось в Angular Github на https://github.com/angular/angular/issues/24571

Думаю это то, на что все переедут

цитата из https://github.com/angular/angular/issues/24571#issuecomment-404606595

For angular components, use the following rules in deciding between:
a) adding initializer
b) make the field optional
c) leave the '!'

If the field is annotated with @input - Make the field optional b) or add an initializer a).
If the input is required for the component user - add an assertion in ngOnInit and apply c.
If the field is annotated @ViewChild, @ContentChild - Make the field optional b).
If the field is annotated with @ViewChildren or @ContentChildren - Add back '!' - c).
Fields that have an initializer, but it lives in ngOnInit. - Move the initializer to the constructor.
Fields that have an initializer, but it lives in ngOnInit and cannot be moved because it depends on other @input fields - Add back '!' - c).

Вы также можете сделать следующее, если действительно не хотите инициализировать его.

makes?: any[];

Это потому, что TypeScript 2.7 включает строгую проверку классов, где все свойства должны быть инициализированы в конструкторе. Обходной путь - добавить ! в качестве постфикса к имени переменной:

makes!: any[];

Вы можете объявить свойство в конструкторе следующим образом:

export class Test {
constructor(myText:string) {
this.myText= myText;
} 

myText: string ;
}

Подход с тестом будет заключаться в добавлении восклицательного знака в конец переменной, для которой вы уверены, что он не должен быть неопределенным или нулевым, например, вы используете ElementRef, который необходимо загрузить из шаблона и может 'не должно быть определено в конструкторе, сделайте что-то вроде ниже

class Component {
 ViewChild('idname') variable! : ElementRef;
}

Другой способ исправить в случае, когда переменная должна оставаться неинициализированной (и это решается во время выполнения), - это добавить undefined к типу (это фактически предлагается кодом VC). Пример:

@Input() availableData: HierarchyItem[] | undefined;
@Input() checkableSettings: CheckableSettings | undefined;

В зависимости от фактического использования это может привести к другим проблемам, поэтому я думаю, что лучший подход - инициализировать свойства, когда это возможно.

Поставьте знак вопроса (?) После того, как сделает переменной.

  makes?: any[];
  vehicle = {};

  constructor(private makeService: MakeService) { }

Теперь он должен работать. Я использую angular 12, и он работает с моим кодом.

Начиная с TypeScript 2.7.2, вы должны инициализировать свойство в конструкторе, если оно не было присвоено в момент объявления.

Если вы используете Vue, вы можете попробовать следующее:

  • Добавьте "strictPropertyInitialization": true к вашему tsconfig.json

  • Если вас не устраивает его отключение, вы также можете попробовать это make: any [] | undefined. Для этого необходимо получить доступ к свойствам с помощью оператора null check (?.), т.е. this.makes? .Length

  • Вы также можете попробовать make !: any [];, это говорит TS, что значение будет присвоено во время выполнения.

При обновлении с использованием typescript@2.9.2 его компилятор строго соблюдает правила для объявления типа массива внутри конструктора класса компонента.

Для устранения этой проблемы либо измените код, который объявлен в коде, либо избегайте добавления компилятором свойства "strictPropertyInitialization": false в файл "tsconfig.json" и запустить снова npm start.

Angular Разработка веб-приложений и мобильных приложений, вы можете перейти на www.jtechweb.in

Вам нужно либо отключить - strictPropertyInitialization, Саджитаран упомянул или сделал что-то вроде этого, чтобы удовлетворить требование инициализации:

makes: any[] = [];

Просто зайдите в tsconfig.json и установите

"strictPropertyInitialization": false

, чтобы избавиться от ошибки компиляции.

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

2022 WebDevInsider