Masukkan Password
56 Properti Indeks (Index Properties)
Tentu. Kita bahas Index Properties di TypeScript dari dasar sampai benar-benar paham, dengan bahasa sederhana dan contoh yang mudah dibayangkan.
1. Apa itu Index Properties?
Index Properties adalah fitur TypeScript yang memungkinkan kita membuat object yang mempunyai property dinamis, yaitu nama property-nya belum kita ketahui sebelumnya atau bisa berbeda-beda.
Biasanya kita membuat interface seperti ini:
interface Product {
id: number;
name: string;
}
Artinya setiap Product harus punya:
id
name
Misalnya:
const product: Product = {
id: 1,
name: "T-Shirt"
};
Masalahnya, bagaimana kalau setiap product bisa mempunyai property tambahan yang berbeda?
Contohnya:
const product1 = {
id: 1,
name: "T-Shirt",
color: "red",
price: 123
};
Sedangkan product lain:
const product2 = {
id: 2,
name: "Mug",
material: "ceramic",
capacity: 300
};
product1 punya:
colorprice
Sedangkan product2 punya:
materialcapacity
Kita tidak tahu dari awal property tambahannya apa saja.
Nah, inilah salah satu situasi di mana Index Properties berguna.
2. Analogi sederhana
Bayangkan kita mempunyai sebuah lemari.
Kita tahu lemari tersebut pasti punya dua laci:
ID
Name
Tetapi kita menyediakan ruang tambahan yang bebas digunakan:
ID
Name
----------------
Property bebas
Property bebas
Property bebas
Property bebas
...
Product A mungkin mengisi:
ID → 1
Name → T-Shirt
Color → Red
Price → 123
Product B:
ID → 2
Name → Mug
Material → Ceramic
Capacity → 300
Jadi:
Index Property = cara mengatakan kepada TypeScript bahwa object boleh memiliki property tambahan dengan nama yang dinamis, selama tipe value-nya sesuai aturan yang kita tentukan.
3. Syntax Index Property
Bentuk dasarnya:
interface Product {
id: number;
name: string;
[prop: string]: string | number;
}
Bagian ini:
[prop: string]: string | number;
adalah index signature.
Mari kita pecah.
prop
[prop: string]
prop hanyalah nama yang kita berikan untuk merepresentasikan nama property.
Namanya bebas.
Misalnya:
[prop: string]
atau:
[key: string]
atau:
[propertyName: string]
Semuanya boleh.
Yang penting adalah:
string
setelah :.
4. Apa arti [prop: string]?
Ini berarti:
“Nama property tambahan boleh berupa string apa saja.”
Misalnya:
color
price
material
capacity
size
brand
category
Semua nama tersebut adalah string.
Jadi TypeScript mengizinkan:
[prop: string]
untuk menerima nama property dinamis.
5. Bagian setelahnya menentukan tipe VALUE
Perhatikan:
[prop: string]: string | number;
Ada dua bagian:
[prop: string]: string | number
↑ ↑
| |
nama property tipe value
Artinya:
Nama property boleh berupa string apa saja, tetapi value-nya hanya boleh
stringataunumber.
Contohnya:
interface Product {
id: number;
name: string;
[prop: string]: string | number;
}
Maka ini valid:
const product: Product = {
id: 1,
name: "T-Shirt",
color: "red",
price: 123,
size: "L"
};
Karena:
id → number ✅
name → string ✅
color → string ✅
price → number ✅
size → string ✅
Tetapi:
const product: Product = {
id: 1,
name: "T-Shirt",
available: true
};
akan bermasalah karena:
available: true
value-nya adalah boolean.
Sedangkan kita menentukan:
[prop: string]: string | number;
Artinya value hanya boleh:
string
atau
number
6. Kenapa id dan name tetap boleh?
Ini bagian yang cukup penting.
Kita punya:
interface Product {
id: number;
name: string;
[prop: string]: string | number;
}
Mungkin muncul pertanyaan:
“Bukankah
[prop: string]sudah mencakupiddannamejuga?”
Iya.
Tetapi property yang kita tulis secara eksplisit tetap mempunyai aturan khusus.
id: number;
name: string;
Jadi:
id: 1
valid karena number.
name: "T-Shirt"
valid karena string.
Dan property tambahan seperti:
color: "red"
price: 123
juga valid karena string | number.
7. Contoh Product secara lengkap
Misalnya:
interface Product {
id: number;
name: string;
[prop: string]: string | number;
}
Kita bisa membuat:
const product1: Product = {
id: 1,
name: "T-Shirt",
color: "red",
price: 123
};
Dan:
const product2: Product = {
id: 2,
name: "Mug",
material: "ceramic",
capacity: 300
};
Perhatikan perbedaannya:
product1
├── id
├── name
├── color
└── price
product2
├── id
├── name
├── material
└── capacity
id dan name selalu ada.
Tetapi property lainnya fleksibel.
8. Kenapa disebut “Index”?
Nama “index” mungkin agak membingungkan karena kita sering mendengar index pada array.
Pada Index Signature, konsepnya adalah kita memberi tahu TypeScript:
“Kalau kamu menemukan property dengan nama yang belum saya definisikan satu per satu, gunakan aturan ini.”
Contohnya:
[prop: string]: string | number;
Artinya kurang lebih:
property apa pun yang namanya string
↓
boleh
↓
asal value-nya string atau number
Jadi kita tidak perlu menulis satu per satu:
color: string;
price: number;
size: string;
material: string;
capacity: number;
brand: string;
Karena kita bisa mengatakan:
[prop: string]: string | number;
9. Index Property tidak harus string
Lecture juga menyebut bahwa index bisa menggunakan number.
Misalnya:
interface Example {
[index: number]: string;
}
Artinya index-nya menggunakan angka.
Namun, dalam praktik TypeScript, string index signature jauh lebih umum untuk object dinamis.
Contoh yang lebih mudah dibayangkan adalah dictionary:
interface Dictionary {
[key: string]: string;
}
Kita bisa mempunyai:
const dictionary: Dictionary = {
name: "John",
city: "London",
country: "England"
};
Nama property-nya bisa berubah-ubah.
10. Use Case #1 — Product dengan property dinamis
Ini adalah contoh pertama dari lecture.
Misalnya aplikasi e-commerce.
Semua product memiliki:
id
name
Tetapi detail product bisa berbeda.
T-Shirt
{
id: 1,
name: "T-Shirt",
color: "red",
size: "L",
price: 123
}
Mug
{
id: 2,
name: "Mug",
material: "ceramic",
capacity: 300
}
Daripada membuat interface yang sangat panjang:
interface Product {
id: number;
name: string;
color?: string;
size?: string;
price?: number;
material?: string;
capacity?: number;
brand?: string;
category?: string;
...
}
kita bisa menggunakan:
interface Product {
id: number;
name: string;
[prop: string]: string | number;
}
Ini jauh lebih fleksibel.
11. Use Case #2 — Settings / Configuration
Ini adalah use case kedua dari lecture.
Bayangkan kita mempunyai aplikasi dengan berbagai settings.
Misalnya:
interface Settings {
[prop: string]: boolean | string | number;
}
Artinya:
Setting apa pun boleh ditambahkan, selama value-nya
boolean,string, ataunumber.
Kemudian:
const mySettings: Settings = {
darkMode: true,
fontSize: 16,
customTheme: "Pink"
};
Perhatikan:
darkMode → boolean
fontSize → number
customTheme → string
Semuanya diperbolehkan karena:
boolean | string | number
12. Kenapa settings cocok menggunakan Index Properties?
Karena kita mungkin tidak tahu semua konfigurasi yang akan tersedia.
Hari ini:
{
darkMode: true,
fontSize: 16
}
Besok mungkin aplikasi menambahkan:
{
darkMode: true,
fontSize: 16,
language: "id",
animation: false,
timeout: 5000
}
Kalau setiap kali ada setting baru kita harus mengubah interface, akan merepotkan.
Index Property memberikan fleksibilitas:
interface Settings {
[key: string]: boolean | string | number;
}
13. Use Case #3 — Collection of Users dengan property berbeda
Contoh ketiga adalah kumpulan user.
Misalnya:
interface User {
name: string;
[prop: string]: any;
}
Kemudian:
const users: User[] = [
{
name: "John",
age: 30,
gender: "male"
},
{
name: "Mark",
interests: ["Music", "Sports"],
location: "London"
}
];
User pertama:
name
age
gender
User kedua:
name
interests
location
Yang sama hanya:
name
Property lainnya berbeda.
14. Tapi hati-hati dengan any
Lecture menggunakan:
[prop: string]: any;
Ini memang memberikan fleksibilitas maksimal.
Contohnya:
interface User {
name: string;
[prop: string]: any;
}
Sekarang semuanya boleh:
const user: User = {
name: "John",
age: 30,
active: true,
hobbies: ["Music", "Sports"],
address: {
city: "London"
}
};
Karena any pada dasarnya mengatakan:
“Value apa pun boleh.”
Tetapi ada konsekuensi.
TypeScript jadi kehilangan banyak manfaat type checking.
Karena itu, kalau memungkinkan, lebih baik gunakan tipe yang spesifik.
Misalnya:
[prop: string]: string | number | boolean;
daripada:
[prop: string]: any;
15. any vs unknown
Kalau memang value benar-benar bisa apa saja, sering kali unknown lebih aman daripada any.
Misalnya:
interface Data {
[key: string]: unknown;
}
Dengan unknown, TypeScript memaksa kita melakukan pengecekan sebelum menggunakan value.
Contohnya:
const data: Data = {
name: "John",
age: 30
};
Kita tidak bisa sembarangan menganggap:
data.name.toUpperCase();
karena TypeScript tahu bahwa value tersebut bisa saja bukan string.
Kita harus mengecek:
if (typeof data.name === "string") {
console.log(data.name.toUpperCase());
}
Ini lebih aman.
16. Perbedaan Property Biasa vs Index Property
Mari bandingkan.
Property biasa
interface User {
name: string;
age: number;
}
Property sudah diketahui:
name
age
Object harus mengikuti struktur tersebut.
Index Property
interface User {
name: string;
[key: string]: string | number;
}
Sekarang:
name
age
city
phone
score
anything...
boleh ditambahkan selama value-nya sesuai.
Jadi:
Property biasa
↓
"Nama property sudah diketahui"
Index Property
↓
"Nama property bisa dinamis"
17. Kenapa tidak pakai object saja?
Pertanyaan bagus.
Kita sebenarnya bisa saja menulis:
const product: object = {
id: 1,
name: "T-Shirt",
color: "red"
};
Tetapi TypeScript tidak mendapatkan informasi struktur yang berguna.
Dengan:
interface Product {
id: number;
name: string;
[key: string]: string | number;
}
TypeScript tahu bahwa:
idharus numbernameharus string- property tambahan boleh ada
- value property tambahan hanya string atau number
Jadi kita mendapatkan fleksibilitas + type safety.
18. Hal penting: Index Signature bukan berarti “semuanya bebas”
Misalnya:
interface Product {
id: number;
name: string;
[key: string]: string | number;
}
Bukan berarti kita bisa memasukkan apa saja.
Ini valid:
const product: Product = {
id: 1,
name: "T-Shirt",
color: "red",
price: 100
};
Tetapi ini tidak:
const product: Product = {
id: 1,
name: "T-Shirt",
available: true
};
Karena:
true
adalah boolean.
Sedangkan aturan kita:
[key: string]: string | number;
19. Visualisasi paling sederhana
Bayangkan interface ini:
interface Product {
id: number;
name: string;
[key: string]: string | number;
}
Secara konsep:
Product
│
┌─────────┴─────────┐
│ │
PROPERTY PROPERTY
TETAP DINAMIS
│ │
┌───┴───┐ ┌───────┴────────┐
│ │ │ │ │
id name color price material
│ │ │ │ │
number string string number string
Jadi ada dua bagian:
Fixed properties
id: number;
name: string;
Dynamic properties
[key: string]: string | number;
20. Bedakan Index Property dengan Optional Property
Ini juga penting.
Optional property
interface Product {
id: number;
name: string;
color?: string;
}
Artinya:
Property
colorsudah diketahui, tetapi boleh ada atau tidak.
Contoh:
{
id: 1,
name: "T-Shirt"
}
valid.
Dan:
{
id: 1,
name: "T-Shirt",
color: "red"
}
juga valid.
Tetapi kita hanya berbicara tentang color.
Index Property
interface Product {
id: number;
name: string;
[key: string]: string | number;
}
Artinya:
Kita tidak tahu property tambahan apa yang akan muncul.
Bisa:
color
bisa:
size
bisa:
price
bisa:
material
dan lain-lain.
Jadi:
Optional Property
→ "Property ini mungkin ada."
Index Property
→ "Property tambahan apa pun mungkin ada."
21. Kapan sebaiknya menggunakan Index Properties?
Gunakan ketika:
1. Nama property belum diketahui
Contoh:
[key: string]: string;
2. Object memiliki property dinamis
Contoh product:
{
id: 1,
name: "T-Shirt",
color: "red",
size: "L"
}
3. Settings / configuration
{
darkMode: true,
fontSize: 16,
language: "id"
}
4. Dictionary / lookup table
Misalnya:
interface Scores {
[username: string]: number;
}
Kemudian:
const scores: Scores = {
john: 90,
mark: 85,
alice: 95
};
Di sini kita tidak tahu username-nya dari awal.
Tetapi kita tahu:
nama username → string
score → number
22. Contoh dictionary yang sangat bagus
Misalnya aplikasi mempunyai daftar harga berdasarkan nama product:
interface Prices {
[productName: string]: number;
}
Kemudian:
const prices: Prices = {
laptop: 1000,
phone: 700,
keyboard: 100
};
Kita tidak perlu membuat:
laptop: number;
phone: number;
keyboard: number;
karena product bisa bertambah kapan saja.
Cukup:
[productName: string]: number;
23. Inti syntax yang harus diingat
Kalau kamu melihat:
[key: string]: number;
bacanya:
“Property name boleh string apa saja, tetapi value-nya harus number.”
Kalau:
[key: string]: string;
bacanya:
“Property name boleh string apa saja, value harus string.”
Kalau:
[key: string]: string | number;
bacanya:
“Property name boleh string apa saja, value boleh string atau number.”
Kalau:
[key: string]: any;
bacanya:
“Property name boleh apa saja dan value apa saja.”
Tetapi any sebaiknya digunakan dengan hati-hati.
24. Satu hal penting tentang nama key
Jangan terlalu fokus pada nama:
[key: string]
key bukan keyword khusus.
Ini juga valid:
[prop: string]: number;
[name: string]: number;
[index: string]: number;
Yang penting adalah struktur:
[namaBebas: tipeNamaProperty]: tipeValue
Misalnya:
[key: string]: number;
25. Ringkasan perbandingan
| Konsep | Artinya |
|---|---|
name: string | Property name harus ada dan string |
color?: string | Property color boleh ada/tidak |
[key: string]: string | Property tambahan boleh dinamis, value harus string |
[key: string]: number | Property tambahan dinamis, value harus number |
[key: string]: string | number | Property dinamis, value string atau number |
[key: string]: any | Property/value sangat bebas, tetapi type safety berkurang |
26. Hubungkan dengan materi sebelumnya
Kalau kita hubungkan dengan materi TypeScript yang sudah kamu pelajari:
Interface
interface Product {
id: number;
name: string;
}
Memberikan struktur object.
Union
string | number
Berarti value boleh:
string ATAU number
Index Property
[key: string]: string | number;
Mengatakan:
“Nama property dinamis, tetapi tipe value-nya dibatasi menggunakan
string | number.”
Jadi Index Property sering bekerja bersama Union Type.
27. Cara membaca contoh lecture secara keseluruhan
Contoh pertama:
interface Product {
id: number;
name: string;
[prop: string]: string | number;
}
Baca seperti ini:
“Setiap Product wajib mempunyai
idberupa number dannameberupa string. Selain itu, Product boleh mempunyai property lain dengan nama apa pun, asalkan value-nya berupa string atau number.”
Contoh:
const product1: Product = {
id: 1,
name: "T-Shirt",
color: "red",
price: 123
};
dan:
const product2: Product = {
id: 2,
name: "Mug",
material: "ceramic",
capacity: 300
};
Keduanya valid karena property tambahannya mengikuti aturan index signature.
28. Kesimpulan paling penting
Kalau harus mengingat satu kalimat saja:
Index Properties digunakan ketika kita ingin membuat object dengan property tambahan yang namanya tidak kita ketahui atau bisa berubah-ubah, tetapi tipe value-nya tetap ingin kita kontrol.
Pola utamanya:
interface Something {
[key: string]: ValueType;
}
Contoh:
interface Settings {
[key: string]: string | number | boolean;
}
Artinya:
Settings
│
▼
nama property bebas
│
▼
value harus salah satu:
string / number / boolean
Dan contoh yang paling gampang diingat:
interface Product {
id: number;
name: string;
[key: string]: string | number;
}
const product: Product = {
id: 1,
name: "T-Shirt",
color: "red",
price: 100,
size: "L"
};
🧠 Cheat sheet
Interface biasa
→ Property sudah diketahui.
Optional property (?)
→ Property diketahui, tapi boleh tidak ada.
Index Property
→ Nama property tambahan tidak diketahui sebelumnya.
[key: string]: string
→ Nama property bebas, value harus string.
[key: string]: string | number
→ Nama property bebas, value harus string atau number.
[key: string]: any
→ Sangat bebas, tapi type safety berkurang.
Kalimat kuncinya:
🔑 Index Property = “Saya tidak tahu nama property tambahannya apa, tetapi saya tahu value-nya harus bertipe apa.”