typescript - error TS2339: Properti 'x' tidak ada pada tipe 'Y'


Saya tidak mengerti mengapa kode ini menghasilkan error TypeScript. (Ini bukan kode asli dan agak dimodifikasi, jadi tolong abaikan hal-hal yang tidak masuk akal dalam contoh ini):

interface Images {
  [key:string]: string;
}

function getMainImageUrl(images: Images): string {
  return images.main;
}

Saya mendapat kesalahan ini (menggunakan TypeScript 1.7.5):

error TS2339: Properti 'main' tidak ada pada tipe 'Images'.

Tentu saja saya bisa menghilangkan kesalahan dengan menulis:

return images["main"];

Saya lebih suka tidak menggunakan string untuk mengakses properti. Apa yang bisa saya lakukan?

Jawaban #1

Perbaikan yang benar adalah menambahkan properti dalam definisi tipe seperti yang dijelaskan dalam jawaban @Nitzan Tomer. Jika itu bukan pilihan:

(Solusi sementara yang tidak rapi) 1

Anda dapat menetapkan objek ke konstanta bertipe any, lalu memanggil properti 'tidak ada'.

const newObj: any = oldObj;
return newObj.someProperty;

Anda juga bisa mengubahnya menjadi any:

return (oldObj as any).someProperty;

Ini gagal memberikan keamanan tipe apa pun, padahal itu adalah inti dari TypeScript.


Solusi Sementara 2

Hal lain yang mungkin Anda pertimbangkan, jika Anda tidak bisa mengubah tipe asli, adalah memperluas tipe seperti ini:

interface NewType extends OldType {
  someProperty: string;
}

Sekarang Anda bisa mengubah variabel Anda menjadi NewType alih-alih any. Masih belum ideal tetapi kurang permisif daripada any, memberi Anda keamanan tipe yang lebih baik.

return (oldObj as NewType).someProperty;

Jawaban #2

Jika Anda ingin dapat mengakses images.main maka Anda harus mendefinisikannya secara eksplisit:

interface Images {
    main: string;
    [key:string]: string;
}

function getMainImageUrl(images: Images): string {
    return images.main;
}

Anda tidak dapat mengakses properti yang diindeks menggunakan notasi titik karena TypeScript tidak memiliki cara untuk mengetahui apakah objek memiliki properti itu atau tidak.
Namun, ketika Anda secara spesifik mendefinisikan sebuah properti, maka compiler tahu bahwa properti itu ada (atau tidak), apakah opsional atau tidak, dan apa tipe datanya.

Sunting

Anda bisa memiliki kelas pembantu untuk instance peta, sesuatu seperti:

class Map<T> {
    private items: { [key: string]: T };

    public constructor() {
        this.items = Object.create(null);
    }

    public set(key: string, value: T): void {
        this.items[key] = value;
    }

    public get(key: string): T {
        return this.items[key];
    }

    public remove(key: string): T {
        let value = this.get(key);
        delete this.items[key];
        return value;
    }
}

function getMainImageUrl(images: Map<string>): string {
    return images.get("main");
}

Saya memiliki sesuatu seperti itu yang diimplementasikan, dan saya merasa itu sangat berguna.

Artikel terkait