Thuộc tính '…' không có bộ khởi tạo và không chắc chắn được gán trong hàm tạo


105

trong ứng dụng Angular của tôi, tôi có một thành phần:

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

nhưng trong tài sản "làm cho" tôi có một sai lầm. Tôi không biết phải làm gì với nó ...

sai lầm

Câu trả lời:


62

Tôi nghĩ rằng bạn đang sử dụng phiên bản TypeScript mới nhất. Vui lòng xem phần "Khởi tạo lớp nghiêm ngặt" trong link.

Có hai cách để sửa lỗi này:

A. Nếu bạn đang sử dụng VSCode, bạn cần thay đổi phiên bản TS mà trình soạn thảo sử dụng.

B. Chỉ khởi tạo mảng khi bạn khai báo nó bên trong hàm tạo,

makes: any[] = [];

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

xin lỗi, tôi là người mới trong bản đánh máy. Bạn có thể nói lỗi của tôi là ở đâu?
Michael Kostiuchenko

2
như lỗi cho biết bạn cần khởi tạo biến thành một số giá trị tạo ra: any [] = [];
Sajeetharan

164

Chỉ cần truy cập tsconfig.json và đặt

"strictPropertyInitialization": false

để loại bỏ lỗi biên dịch.

Nếu không, bạn cần phải khởi tạo tất cả các biến của mình, điều này hơi khó chịu


3
Chỉ cần đảm bảo rằng bạn thêm điều đó vào sau "nghiêm ngặt": true nếu không trình chuyển tiếp dường như sẽ bật lại (mặc dù VS dường như biết nó đang tắt).
monty

36
Bằng cách này, bạn sẽ vô hiệu hóa việc khởi tạo thuộc tính kiểm tra nghiêm ngặt cho tất cả dự án. Tốt hơn là thêm !toán tử postfix vào tên biến, để bỏ qua trường hợp này hoặc khởi tạo biến bên trong hàm tạo.
Matteo Guarnerio,

6
Bạn đang đề nghị bỏ qua các vấn đề tiềm ẩn mà trình biên dịch đang nói về, điều này không thực sự an toàn. Vì vậy, downvote.
Olga

6
Nghiêm ngặt là một cờ được giới thiệu trong phiên bản 2.7. Mọi người có quyền lựa chọn nếu bạn muốn bật tất cả các cờ này và tuân thủ nghiêm ngặt tất cả các quy tắc hoặc tắt một số xác thực. Hoàn toàn không có ý nghĩa gì khi tuân theo tất cả các quy tắc mọi lúc. Nếu mã của bạn quá dài dòng và nhiều nhược điểm và lớn hơn lợi thế, bạn nên tắt nó đi. Tôi không nói rằng đây là thực hành tốt nhất trong mọi trường hợp nhưng tùy chọn chắn khả thi của nó trong nhiều trường hợp ...
Martin Čuka

1
Như tôi đã đề cập trong câu trả lời của mình, bạn có hai tùy chọn hoặc bạn tắt xác thực HOẶC khởi tạo tất cả các biến. Tùy thuộc vào mọi người để lựa chọn những gì bạn sẽ được lợi nhiều hơn từ dự án này sang dự án khác.
Martin Čuka

49

Đó là bởi vì TypeScript 2.7 bao gồm một kiểm tra lớp nghiêm ngặt, nơi tất cả các thuộc tính nên được khởi tạo trong phương thức khởi tạo. Một cách giải quyết là thêm !dưới dạng hậu tố vào tên biến:

makes!: any[];

12
Các "!" cú pháp tồn tại cho những trường hợp thông thường mà bạn không thể đảm bảo rằng giá trị sẽ được xác định ngay lập tức. Đó là một lối thoát hiểm và không nên dựa vào, vì nó có thể làm cho mã của bạn kém an toàn hơn. Giá trị mặc định thường được ưu tiên. Thông tin cần biết nó tồn tại, mặc dù
kingdaro

@kingdaro nói đúng. Mặc dù điều này thường có thể được sử dụng, nhưng nó cũng có thể dẫn đến mã phẳng không hoạt động. Ví dụ: trong ứng dụng web cơ bản được tạo bởi VS2017, hãy thay đổi chỉ định cho các dự báo trong fetchdata.components.ts bằng cách thêm '!' (dự báo công khai !: WeatherForecast [];) và nó sẽ khiến nó hoàn toàn bị lỗi
IronRod

14

Chúng tôi có thể nhận được thông báo Property has no initializer and is not definitely assigned in the constructorkhi thêm một số cấu hình trong tsconfig.jsontệp để có một dự án Angular được biên dịch ở chế độ nghiêm ngặt:

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

Thật vậy, trình biên dịch sau đó phàn nàn rằng một biến thành viên không được định nghĩa trước khi được sử dụng.

Ví dụ về một biến thành viên không được xác định tại thời điểm biên dịch, một biến thành viên có một @Inputchỉ thị:

@Input() userId: string;

Chúng tôi có thể tắt tiếng trình biên dịch bằng cách nêu biến có thể là tùy chọn:

@Input() userId?: string;

Nhưng sau đó, chúng ta sẽ phải đối phó với trường hợp biến không được xác định và làm lộn xộn mã nguồn với một số câu lệnh như vậy:

if (this.userId) {
} else {
}

Thay vào đó, khi biết giá trị của biến thành viên này sẽ được xác định đúng lúc, tức là nó sẽ được định nghĩa trước khi được sử dụng, chúng ta có thể nói với trình biên dịch đừng lo lắng về việc nó không được định nghĩa.

Cách để thông báo điều này với trình biên dịch là thêm ! definite assignment assertiontoán tử, như trong:

@Input() userId!: string;

Bây giờ, trình biên dịch hiểu rằng biến này, mặc dù không được định nghĩa tại thời điểm biên dịch, nhưng sẽ được xác định tại thời điểm chạy và trong thời gian, trước khi nó được sử dụng.

Bây giờ ứng dụng phải đảm bảo biến này được xác định trước khi được sử dụng.

Như một biện pháp bảo vệ bổ sung, chúng tôi có thể khẳng định biến đang được xác định trước khi chúng tôi sử dụng.

Chúng ta có thể khẳng định biến đã được định nghĩa, nghĩa là, ràng buộc đầu vào bắt buộc đã thực sự được cung cấp bởi ngữ cảnh gọi:

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

Biết biến đã được định nghĩa, biến bây giờ có thể được sử dụng:

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

Lưu ý rằng ngOnInitphương thức được gọi sau khi các liên kết đầu vào cố gắng, điều này, ngay cả khi không có đầu vào thực tế nào được cung cấp cho các liên kết.

Trong khi ngOnChangesphương thức được gọi sau khi các liên kết đầu vào cố gắng thực hiện và chỉ khi có đầu vào thực sự được cung cấp cho các liên kết.


đây là câu trả lời chính xác khi sử dụng chế độ 'nghiêm ngặt'
RnDrx

9

Bạn cần phải vô hiệu hóa --strictPropertyInitializationmà Sajeetharan đã đề cập đến hoặc làm điều gì đó như thế này để đáp ứng yêu cầu khởi tạo:

makes: any[] = [];

6

Bạn cũng có thể làm như sau nếu bạn thực sự không muốn khởi tạo nó.

makes?: any[];

5

Kể từ TypeScript 2.7.2, bạn được yêu cầu khởi tạo một thuộc tính trong phương thức khởi tạo nếu nó không được gán tại thời điểm khai báo.

Nếu bạn đến từ Vue, bạn có thể thử những cách sau:

  • Thêm "strictPropertyInitialization": truevào tsconfig.json của bạn

  • Nếu bạn không hài lòng với việc tắt nó, bạn cũng có thể thử cách này makes: any[] | undefined. Làm điều này yêu cầu bạn truy cập các thuộc tính với ?.toán tử null check ( ) tức làthis.makes?.length

  • Bạn cũng có thể thử makes!: any[];, điều này cho TS biết rằng giá trị sẽ được chỉ định trong thời gian chạy.

3

Khi bạn nâng cấp bằng cách sử dụng stylescript@2.9.2, trình biên dịch của nó sẽ tuân theo các quy tắc nghiêm ngặt đối với khai báo kiểu mảng bên trong hàm tạo lớp thành phần.

Để khắc phục sự cố này, hãy thay đổi mã nơi được khai báo trong mã hoặc tránh chuyển sang trình biên dịch để thêm thuộc tính "securePropertyInitialization": false trong tệp "tsconfig.json" và chạy lại npm start.

Phát triển ứng dụng di động và web Angular, bạn có thể truy cập www.jtechweb.in


2

Bạn không thể chỉ sử dụng Phép chỉ định xác định? (Xem https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#definite-assignment-assertions )

tức là khai báo thuộc tính là makes!: any[];The! đảm bảo rằng bản ghi chắc chắn sẽ có một giá trị trong thời gian chạy.

Xin lỗi, tôi chưa thử điều này trong góc độ nhưng nó hoạt động rất tốt cho tôi khi tôi gặp vấn đề chính xác trong React.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.