속성 '…'에는 이니셜 라이저가 없으며 생성자에 확실히 할당되지 않았습니다.


134

내 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);
  }
}

하지만 "만들다"속성에 실수가 있습니다. 나는 그것으로 무엇을 해야할지 모르겠다 ...

잘못

답변:


81

최신 버전의 TypeScript를 사용하고 있다고 생각합니다. 의 "Strict Class Initialization"섹션을 참조하십시오 link.

이 문제를 해결하는 방법에는 두 가지가 있습니다.

A. VSCode를 사용하는 경우 편집기에서 사용하는 TS 버전을 변경해야합니다.

B. 생성자 내부에서 선언 할 때 배열을 초기화합니다.

makes: any[] = [];

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

죄송합니다. 저는 타이프 스크립트가 처음입니다. 내 실수가 어디 있는지 말할 수 있습니까?
Michael Kostiuchenko 18:41에

2
오류에서 변수를 어떤 값으로 초기화해야한다고 말했듯이 : any [] = [];
Sajeetharan

1
이 변수가 런타임에 다음과 같이 값을 가질 것임을 typescript에 알리려면 'Definite Assignment Assertion'을 사용해야합니다.makes!: any[];
Hussein Akar

211

그냥 이동 tsconfig.json 및 설정

"strictPropertyInitialization": false

컴파일 오류를 제거합니다.

그렇지 않으면 조금 성가신 모든 변수를 초기화해야합니다.


4
"strict"뒤에 추가했는지 확인하십시오. 그렇지 않으면 트랜스 파일러가 다시 켜는 것처럼 보입니다 (VS는 꺼져있는 것 같지만).
monty

52
이런 식으로 모든 프로젝트에 대해 엄격한 검사 속성 초기화를 비활성화합니다. !이 경우를 무시하거나 생성자 내에서 변수를 초기화하려면 변수 이름에 접미사 연산자 를 추가하는 것이 좋습니다 .
Matteo Guarnerio

10
컴파일러가 말하고있는 잠재적 인 문제를 무시하라고 제안하는 것입니다. 이것은 실제로 안전하지 않습니다. 그래서 반대 투표.
Olga

7
StrictPropertyInitialzer는 typescript 2.7에 도입 된 플래그입니다. 이러한 모든 플래그를 활성화하고 모든 규칙을 엄격하게 따르거나 일부 유효성 검사를 끌 것인지 여부는 모든 사람이 선택해야합니다. 매번 모든 규칙을 따르는 것은 전혀 의미가 없습니다. 코드가 너무 장황하고 단점이 있고 장점보다 크면 확실히 해제해야합니다. 나는이 모든 경우에 가장 좋은 방법은 있지만, 대부분의 경우에 그의 definetly 실행 가능한 옵션 ...라고 이야기하고 있지 않다
마틴하는 CuKα

2
내 대답에서 언급했듯이 유효성 검사를 비활성화하거나 모든 변수를 초기화하는 두 가지 옵션이 있습니다. 프로젝트마다 더 많은 혜택을 누릴 수있는 것은 모두가 선택할 수 있습니다.
Martin Čuka

68

TypeScript 2.7에는 생성자에서 모든 속성을 초기화해야하는 엄격한 클래스 검사가 포함되어 있기 때문입니다. 해결 방법은 !변수 이름에 접미사로 를 추가하는 것입니다.

makes!: any[];

12
"!" 구문은 값이 즉시 정의된다는 것을 보장 할 수없는 일반적인 경우에 존재합니다. 탈출구이며 코드의 안전성을 떨어 뜨릴 수 있으므로 의존해서는 안됩니다. 일반적으로 기본값이 선호됩니다. 그러나 그것이 존재한다는 것을 아는 것은 좋은
kingdaro

@kingdaro가 맞습니다. 이것은 일반적으로 사용될 수 있지만 플랫이 작동하지 않는 코드로 이어질 수도 있습니다. 예를 들어, VS2017에서 생성 된 기본 웹앱에서 '!'를 추가하여 fetchdata.components.ts의 예측 할당을 변경합니다. (공개 예측! : WeatherForecast [];) 그리고 그것은 완전히 오류를 일으킬 것입니다
IronRod

이것은 @Input () 데코레이터 (새 각도에서) 바로 뒤에 있기 때문에 주어진 구성 요소를 읽을 때 자연스럽게 읽고 개발 실수를 제거하기 때문에 최상의 솔루션입니다.
ELI7VH

23

Angular 프로젝트를 엄격 모드로 컴파일하기 Property has no initializer and is not definitely assigned in the constructor위해 tsconfig.json파일에 일부 구성을 추가 할 때 메시지가 표시 될 수 있습니다.

"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 {
}

대신,이 멤버 변수의 값을 알면 시간 내에 정의됩니다. 즉, 사용되기 전에 정의되므로 컴파일러에게 정의되지 않는 것에 대해 걱정하지 않도록 할 수 있습니다.

이것을 컴파일러에 알리는 방법은 다음 ! definite assignment assertion과 같이 연산자 를 추가하는 것입니다.

@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방법은 입력 바인딩 시도 후 불러에만 바인딩 제공 실제 입력되어 있었다.


이것은 'strict'모드를 사용할 때 정답입니다
RnDrx

한 가지를 제외하고이 많은 것들이 나에게 의미가 있습니다 ... 그 주장이 당신에게 무엇을 줄까요? 디버깅에는 좋지만 앱 사용에는 적합하지 않습니다. 잡히지 않을 오류를 던지는 것은 좋은 생각이 아닙니다. 무슨 일이 있어도 작동하도록 몇 가지 폴백을 제공해야합니다.
Nux

8

초기화하고 싶지 않은 경우 다음을 수행 할 수도 있습니다.

makes?: any[];

8

--strictPropertyInitializationSajeetharan이 언급 한 기능 을 비활성화 하거나 초기화 요구 사항을 충족하려면 다음과 같이해야합니다.

makes: any[] = [];

6

TypeScript 2.7.2부터 선언 시점에 할당되지 않은 경우 생성자에서 속성을 초기화해야합니다.

Vue에서 오는 경우 다음을 시도 할 수 있습니다.

  • "strictPropertyInitialization": truetsconfig.json에 추가

  • 비활성화하는 것이 만족스럽지 않다면 이것을 시도 할 수도 있습니다 makes: any[] | undefined. 이렇게하려면 null 확인 ( ?.) 연산자 를 사용하여 속성에 액세스해야합니다.this.makes?.length

  • 시도해 볼 수도 있습니다 makes!: any[];. 이것은 TS에게 값이 런타임에 할당된다는 것을 알려줍니다.

4

typescript@2.9.2를 사용하여 업그레이드 할 때 컴파일러는 구성 요소 클래스 생성자 내부에서 배열 유형 선언에 대한 규칙을 엄격하게 따릅니다.

이 문제를 해결하려면 코드에서 선언 된 코드를 변경하거나 "tsconfig.json""strictPropertyInitialization" 속성을 추가하는 컴파일러를 피하십시오 . false 파일 하고 npm start를 다시 실행 .

Angular 웹 및 모바일 응용 프로그램 개발은 www.jtechweb.in으로 이동할 수 있습니다.


3

Definite Assignment Assertion을 사용할 수 없습니까? ( https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#definite-assignment-assertions 참조 )

즉, 속성을 다음과 같이 선언 makes!: any[]; The! 런타임에 확실히 값이있을 것이라는 typescript를 보장합니다.

죄송하지만 각도에서 시도하지 않았지만 React에서 똑같은 문제가 발생했을 때 잘 작동했습니다.


공식 문서에 있으므로 모든 버전으로 작업하고 시도했습니다. 감사!!
Hussein Akar

3

내 Angular 프로젝트에 노드를 추가 할 때이 오류가 발생합니다.

TSError :? TypeScript를 컴파일 할 수 없음 : (path) /base.api.ts:19:13-오류 TS2564 : 속성 'apiRoot Path'에 이니셜 라이저가 없으며 생성자에 확실히 할당되지 않았습니다.

개인 apiRootPath : 문자열;

해결책 -

tsconfig.json의"strictPropertyInitialization": false 'compilerOptions'에 추가되었습니다 . .

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/


2

이 오류는 합법적 이며 앱 충돌을 방지 할 수 있습니다. makes배열로 입력 했지만 정의되지 않을 수도 있습니다.

두 가지 옵션이 있습니다 (기존에 대한 typescript의 이유를 비활성화하는 대신 ...) :

1. 귀하의 경우 가장 좋은 방법은 makes정의되지 않은 것으로 입력 하는 것입니다.

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

이 경우 컴파일러는 액세스를 시도 할 때마다 makes정의되지 않았을 수 있음 을 알려줍니다 . 예를 들어 완료 // <-- Not ok하기 전에 아래 줄 을 작성 getMakes하거나 getMakes실패하면 컴파일 오류가 발생합니다. 그렇지 않으면 응용 프로그램이 충돌합니다.

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

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

2. 아래 코드를 작성하여 실패하지 않고 초기화 전에 액세스를 시도하지 않을 것이라고 가정 할 수 있습니다 (위험합니다!). 따라서 컴파일러는이를 처리하지 않습니다.

makes!: any[]

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.