Saya selalu mengkompilasi naskah dengan flag --noImplicitAny. Ini masuk akal karena saya ingin memeriksa tipe saya sekencang mungkin.
Masalah saya adalah bahwa dengan kode berikut ini saya mendapatkan kesalahan Index signature of object type implicitly has an 'any' type
:
interface ISomeObject {
firstKey: string;
secondKey: string;
thirdKey: string;
}
let someObject: ISomeObject = {
firstKey: 'firstValue',
secondKey: 'secondValue',
thirdKey: 'thirdValue'
};
let key: string = 'secondKey';
let secondValue: string = someObject[key];
Penting untuk dicatat adalah idenya adalah bahwa variabel kunci berasal dari tempat lain dalam aplikasi dan dapat berupa salah satu kunci dalam objek.
Saya sudah mencoba secara eksplisit casting type dengan:
let secondValue: string = <string>someObject[key];
Atau skenario saya tidak mungkin dengan --noImplicitAny
?
sumber
Cara lain untuk menghindari kesalahan adalah dengan menggunakan para pemain seperti ini:
let secondValue: string = (<any>someObject)[key];
(Perhatikan tanda kurung)Satu-satunya masalah adalah bahwa ini bukan tipe-aman lagi, karena Anda casting ke
any
. Tetapi Anda selalu dapat kembali ke jenis yang benar.ps: Saya menggunakan naskah 1.7, tidak yakin tentang versi sebelumnya.
sumber
let secondValue: string = (someObject as any)[key];
TypeScript 2.1 memperkenalkan cara yang elegan untuk menangani masalah ini.
Kami dapat mengakses semua nama properti objek selama fase kompilasi dengan
keyof
kata kunci (lihat changelog ).Anda hanya perlu mengganti
string
tipe variabel dengankeyof ISomeObject
. Sekarang kompiler tahukey
variabel diizinkan hanya berisi nama properti dariISomeObject
.Contoh lengkap:
Kode langsung di typescriptlang.org (
noImplicitAny
opsi setel )Bacaan lebih lanjut dengan lebih banyak
keyof
penggunaan .sumber
key
sebagaiconst key = (keyof ISomeObject)
= 'detik' + 'Kunci'Berikut pengaturan tsconfig akan memungkinkan Anda untuk mengabaikan kesalahan ini - setel ke true.
sumber
--noImplicitAny
. Cocokkan dengan sempurna pertanyaan op.XMLHttpRequest
.keyof
Operator TS2.1 dapat membantu menjaga semuanya tetap ketat, lihat jawaban Piotr!Solusi 'keyof' yang disebutkan di atas berfungsi. Tetapi jika variabel digunakan hanya sekali misalnya perulangan melalui objek dll, Anda juga dapat mengetikkannya.
sumber
menggunakan
keyof typeof
sumber
Mirip dengan jawaban @Piotr Lewandowski, tetapi dalam
forEach
:sumber
Argument of type '(field: "id" | "url" | "name") => void' is not assignable to parameter of type '(value: string, index: number, array: string[]) => void'
. Kode saya terlihat seperti ituObject.keys(components).forEach((comp: Component) => {...}
, di manaComponent
ada tipe (sepertiMyConfig
).Nyatakan objek seperti ini.
sumber
Tidak ada pengindeks? Lalu buat sendiri!
Saya secara global mendefinisikan ini sebagai cara mudah untuk mendefinisikan tanda tangan objek.
T
bisaany
jika diperlukan:Saya hanya menambahkan
indexer
sebagai anggota kelas.Jadi saya berakhir dengan ini:
Manfaat melakukan ini adalah Anda mendapatkan kembali tipe yang tepat - banyak solusi yang digunakan
<any>
akan kehilangan mengetik untuk Anda. Ingat ini tidak melakukan verifikasi runtime. Anda masih perlu memeriksa apakah ada sesuatu jika Anda tidak tahu pasti itu ada.Jika Anda ingin sangat berhati-hati, dan Anda menggunakan
strict
Anda dapat melakukan ini untuk mengungkapkan semua tempat Anda mungkin perlu melakukan pemeriksaan yang tidak ditentukan secara eksplisit:Saya biasanya tidak menemukan ini diperlukan karena jika saya memiliki properti string dari suatu tempat saya biasanya tahu bahwa itu valid.
Saya menemukan metode ini sangat berguna jika saya memiliki banyak kode yang perlu mengakses pengindeks, dan pengetikan dapat diubah hanya dalam satu tempat.
Catatan: Saya menggunakan
strict
mode, danunknown
itu pasti diperlukan.Kode yang dikompilasi hanya akan
indexer = this
, jadi sangat mirip dengan saat naskah dibuat_this = this
untuk Anda.sumber
Record<T>
jenis sebagai gantinya - Saya tidak dapat saat ini untuk meneliti detail halus ini, tetapi untuk beberapa kasus terbatas ini dapat bekerja lebih baik.Buat antarmuka untuk mendefinisikan antarmuka 'pengindeks'
Kemudian buat objek Anda dengan indeks itu.
Catatan: ini akan tetap memiliki masalah yang sama dengan jawaban lain yang dijelaskan sehubungan dengan menegakkan jenis setiap item - tetapi itu sering kali persis seperti yang Anda inginkan.
Anda dapat membuat parameter tipe generik apa pun yang Anda butuhkan:
ObjectIndexer< Dog | Cat>
Taman Bermain Anak
Anda bahkan dapat menggunakan ini dalam batasan generik ketika mendefinisikan tipe generik:
export class SmartFormGroup<T extends IndexableObject<any>> extends FormGroup
Kemudian
T
di dalam kelas dapat diindeks :-)sumber
Dictionary
yang mewakili{ [key: string]: T }
, tetapi jika ada silakan edit pertanyaan ini untuk menghapus sayaObjectIndexer
.Nyatakan tipe yang kuncinya adalah string dan nilainya dapat berupa apa saja kemudian mendeklarasikan objek dengan tipe ini dan serat tidak akan muncul
Jadi kode Anda akan menjadi
sumber
Saat ini solusi yang lebih baik adalah dengan mendeklarasikan tipe. Suka
sumber
Solusi paling sederhana yang bisa saya temukan menggunakan TypeScript 3.1 dalam 3 langkah adalah:
1) Buat antarmuka
2) Buat salinan yang diketik
3) Gunakan di mana saja (termasuk BEJ)
sumber