Properti '…' tidak memiliki penginisialisasi dan tidak ditetapkan secara pasti di konstruktor

132

di aplikasi Angular saya, saya memiliki komponen:

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

tetapi di properti "membuat" saya memiliki kesalahan. Saya tidak tahu harus berbuat apa dengannya ...

kesalahan

Michael Kostiuchenko
sumber

Jawaban:

73

Saya rasa Anda menggunakan TypeScript versi terbaru. Silakan lihat bagian "Inisialisasi Kelas Ketat" di link.

Ada dua cara untuk memperbaikinya:

A. Jika Anda menggunakan VSCode, Anda perlu mengubah versi TS yang digunakan editor.

B. Cukup inisialisasi array ketika Anda mendeklarasikannya di dalam konstruktor,

makes: any[] = [];

constructor(private makeService: MakeService) { 
   // Initialization inside the constructor
   this.makes = [];
}
Sajeetharan
sumber
maaf, saya baru dalam naskah ketikan. Bisakah Anda mengatakan di mana kesalahan saya?
Michael Kostiuchenko
2
karena kesalahan mengatakan Anda perlu menginisialisasi variabel ke beberapa nilai makes: any [] = [];
Sajeetharan
1
Anda harus menggunakan 'Definite Assignment Assertion' untuk memberi tahu skrip ketikan bahwa variabel ini akan memiliki nilai saat runtime sebagai berikut:makes!: any[];
Hussein Akar
207

Buka saja tsconfig.json dan set

"strictPropertyInitialization": false

untuk menghilangkan kesalahan kompilasi.

Jika tidak, Anda perlu menginisialisasi semua variabel Anda yang sedikit mengganggu

Martin Čuka
sumber
3
Pastikan Anda menambahkannya setelah "strict": true jika tidak transpiler akan menyalakannya lagi (walaupun VS sepertinya tahu itu mati).
monty
52
Dengan cara ini Anda akan menonaktifkan inisialisasi properti pemeriksaan ketat untuk semua proyek. Lebih baik menambahkan !operator postfix ke nama variabel, mengabaikan kasus ini, atau menginisialisasi variabel di dalam konstruktor.
Matteo Guarnerio
10
Anda menyarankan untuk mengabaikan potensi masalah yang diceritakan oleh kompilator, ini tidak benar-benar aman. Jadi tidak setuju.
Olga
6
StrictPropertyInitialzer adalah tanda yang diperkenalkan di skrip ketikan 2.7. Terserah semua orang untuk memilih apakah Anda ingin mengaktifkan semua bendera ini dan mengikuti semua aturan secara ketat atau menonaktifkan beberapa validasi. Sangat tidak masuk akal untuk mengikuti semua aturan setiap saat. Jika kode Anda terlalu bertele-tele dan merugikan dan lebih besar dari keuntungan, Anda harus mematikannya. Saya tidak mengatakan bahwa ini adalah praktik terbaik dalam semua kasus, tetapi opsi yang pasti layak dalam banyak kasus ...
Martin Čuka
2
ketika saya menyetelnya ke false, masih ada kesalahan yang sama, apa masalahnya? Saya menggunakan VS Code
sertsedat
66

Itu karena TypeScript 2.7 menyertakan pemeriksaan kelas yang ketat di mana semua properti harus diinisialisasi dalam konstruktor. Solusinya adalah dengan menambahkan !sebagai postfix ke nama variabel:

makes!: any[];
Harinath
sumber
12
The "!" sintaksis ada untuk kasus-kasus common-ish di mana Anda tidak dapat menjamin bahwa nilainya akan segera ditentukan. Ini adalah jalan keluar, dan tidak boleh diandalkan, karena dapat membuat kode Anda menjadi kurang aman. Nilai default biasanya lebih disukai. Senang mengetahui itu ada, meskipun
kingdaro
@kingdaro benar. Meskipun ini umumnya dapat digunakan, ini juga dapat menyebabkan kode yang datar tidak berfungsi. Sebagai contoh, di aplikasi web dasar yang dibuat oleh VS2017, ubah penetapan untuk perkiraan di fetchdata.components.ts dengan menambahkan '!' (prakiraan publik !: Prakiraan Cuaca [];) dan itu akan menyebabkan kesalahan sepenuhnya
IronRod
Ini adalah solusi terbaik, karena ini tepat setelah dekorator @Input () (dalam sudut baru), saat membaca komponen yang diberikan, ia membaca secara alami dan menyingkirkan kesalahan dev.
ELI7VH
22

Kita mungkin mendapatkan pesan Property has no initializer and is not definitely assigned in the constructorsaat menambahkan beberapa konfigurasi dalam tsconfig.jsonfile tersebut sehingga proyek Angular dapat dikompilasi dalam mode ketat:

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

Memang kompilator kemudian mengeluh bahwa variabel anggota tidak ditentukan sebelum digunakan.

Untuk contoh variabel anggota yang tidak ditentukan pada waktu kompilasi, variabel anggota memiliki @Inputarahan:

@Input() userId: string;

Kami dapat membungkam kompilator dengan menyatakan variabel mungkin opsional:

@Input() userId?: string;

Tapi kemudian, kita harus berurusan dengan kasus variabel yang tidak didefinisikan, dan mengacaukan kode sumber dengan beberapa pernyataan seperti itu:

if (this.userId) {
} else {
}

Sebaliknya, mengetahui nilai variabel anggota ini akan ditentukan dalam waktu, yaitu, akan ditentukan sebelum digunakan, kita dapat memberi tahu kompilator untuk tidak khawatir tentang hal itu tidak didefinisikan.

Cara untuk memberitahukannya ke kompilator adalah dengan menambahkan ! definite assignment assertionoperator, seperti di:

@Input() userId!: string;

Sekarang, kompilator memahami bahwa variabel ini, meskipun tidak didefinisikan pada waktu kompilasi, harus didefinisikan pada saat run-time, dan pada waktunya, sebelum digunakan.

Sekarang terserah aplikasi untuk memastikan variabel ini ditentukan sebelum digunakan.

Sebagai perlindungan tambahan, kita dapat menegaskan bahwa variabel sedang didefinisikan, sebelum kita menggunakannya.

Kita dapat menegaskan bahwa variabel telah ditentukan, yaitu, pengikatan input yang diperlukan sebenarnya disediakan oleh konteks panggilan:

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

Mengetahui variabel telah ditentukan, variabel tersebut sekarang dapat digunakan:

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

Perhatikan bahwa ngOnInitmetode ini dipanggil setelah percobaan pengikatan input, ini, meskipun tidak ada masukan aktual yang diberikan ke pengikatan.

Sedangkan ngOnChangesmetode ini dipanggil setelah percobaan pengikatan masukan, dan hanya jika ada masukan aktual yang diberikan ke pengikatan.

Stephane
sumber
ini adalah jawaban yang benar saat menggunakan mode 'ketat'
RnDrx
8

Anda juga dapat melakukan hal berikut jika Anda benar-benar tidak ingin memulainya.

makes?: any[];
SpeedOfSpin
sumber
8

Anda juga perlu menonaktifkan --strictPropertyInitializationSajeetharan yang dimaksud, atau melakukan sesuatu seperti ini untuk memenuhi persyaratan inisialisasi:

makes: any[] = [];
kshetline
sumber
6

Mulai TypeScript 2.7.2, Anda diminta untuk menginisialisasi properti di konstruktor jika tidak ditetapkan ke titik deklarasi.

Jika Anda berasal dari Vue, Anda dapat mencoba yang berikut ini:

  • Tambahkan "strictPropertyInitialization": trueke tsconfig.json Anda

  • Jika Anda tidak senang menonaktifkannya, Anda juga dapat mencoba ini makes: any[] | undefined. Melakukan hal ini mengharuskan Anda mengakses properti dengan ?.operator null check ( ) yaituthis.makes?.length

  • Anda juga bisa mencoba makes!: any[];, ini memberi tahu TS bahwa nilai akan ditetapkan pada waktu proses.
codejockie
sumber
4

Ketika Anda mengupgrade menggunakan [email protected], kompilernya ketat mengikuti aturan untuk tipe array yang dideklarasikan di dalam konstruktor kelas komponen.

Untuk memperbaiki masalah ini, baik ubah kode yang dideklarasikan dalam kode atau hindari compiler untuk menambahkan properti "strictPropertyInitialization": false di file "tsconfig.json" dan jalankan lagi npm start.

Web Angular dan Pengembangan Aplikasi seluler Anda dapat mengunjungi www.jtechweb.in

Jai Govind Gupta
sumber
3

Tidak bisakah Anda menggunakan Definite Assignment Assertion? (Lihat https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#definite-assignment-assertions )

yaitu mendeklarasikan properti sebagai makes!: any[];The! memastikan ketikan bahwa pasti akan ada nilai pada waktu proses.

Maaf, saya belum mencoba ini dalam sudut tetapi berhasil dengan baik untuk saya ketika saya mengalami masalah yang sama persis di React.

Andy
sumber
Bekerja dengan semua versi karena ada dalam dokumentasi resmi dan saya mencobanya. TERIMA KASIH!!
Hussein Akar
3

Dapatkan kesalahan ini pada saat menambahkan Node di proyek Angular saya -

TSError:? Tidak dapat mengkompilasi TypeScript: (path) /base.api.ts:19:13 - error TS2564: Properti 'apiRoot Path' tidak memiliki penginisialisasi dan tidak ditetapkan secara pasti di konstruktor.

apiRootPath pribadi: string;

Solusi -

Ditambahkan "strictPropertyInitialization": falsedalam 'compilerOptions' dari tsconfig.json .

package.json saya -

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

URL Ref - https://www.ryadel.com/en/ts2564-ts-property-has-no-initializer-typescript-error-fix-visual-studio-2017-vs2017/

Pinaki
sumber
2

Kesalahan ini sah dan dapat mencegah aplikasi Anda mogok. Anda mengetik makessebagai array tetapi bisa juga tidak ditentukan.

Anda memiliki 2 opsi (daripada menonaktifkan alasan skrip ketikan untuk ...):

1. Dalam kasus Anda, yang terbaik adalah mengetik makesdengan kemungkinan tidak terdefinisi.

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

Dalam hal ini kompilator akan memberi tahu Anda setiap kali Anda mencoba mengakses makesyang mungkin tidak ditentukan. Misalnya jika Anda menulis // <-- Not okbaris di bawah ini sebelum getMakesselesai atau jika getMakesgagal, kesalahan kompilasi akan muncul. Jika tidak, aplikasi Anda akan macet.

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

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

2. Anda dapat berasumsi bahwa ini tidak akan pernah gagal dan bahwa Anda tidak akan pernah mencoba mengaksesnya sebelum inisialisasi dengan menulis kode di bawah ini (berisiko!). Jadi kompilator tidak akan mempedulikannya.

makes!: any[]
Alexandre Annic
sumber
0

mengubah

fieldname?: any[]; 

untuk ini:

fieldname?: any; 
MAM.AASIM
sumber