Masukkan Password
33 Rantai Opsional (Optional Chaining)
Kita bahas Optional Chaining (?.) secara perlahan, karena konsep ini sebenarnya sederhana, tetapi akan terasa sangat berguna ketika mulai berurusan dengan object yang datanya tidak selalu lengkap, misalnya data dari API, database, atau DOM.
1. Apa itu Optional Chaining?
Optional Chaining adalah operator yang ditulis:
?.
Tujuannya adalah:
Mengakses property atau memanggil sesuatu dengan aman ketika object sebelumnya mungkin
nullatauundefined.
Contoh paling sederhana:
const user = {
name: "John"
};
console.log(user.address?.city);
Di sini user.address tidak ada.
Kalau kita menulis:
user.address.city
JavaScript akan error karena:
user.address
↓
undefined
↓
undefined.city
↓
ERROR ❌
Tetapi kalau:
user.address?.city
JavaScript akan berhenti dengan aman dan menghasilkan:
undefined
Jadi:
user.address
↓
undefined?
↓
YES
↓
berhenti di sini
↓
undefined
Itulah fungsi utama Optional Chaining.
2. Kenapa kita membutuhkan Optional Chaining?
Mari gunakan contoh yang mirip dengan lecture.
Misalnya kita punya data produk:
const products = [
{
name: "iPhone",
price: 1000,
details: {
color: "black",
ram: "8GB"
}
},
{
name: "T-Shirt",
price: 20,
details: {
color: "white",
size: "L"
}
},
{
name: "Book",
price: 15,
pages: 300,
author: "John Smith"
}
];
Perhatikan struktur datanya.
Produk pertama:
iPhone
├── name
├── price
└── details
├── color
└── ram
Produk kedua:
T-Shirt
├── name
├── price
└── details
├── color
└── size
Produk ketiga:
Book
├── name
├── price
├── pages
└── author
Book tidak memiliki details.
Nah, masalah muncul ketika kita melakukan:
prod.details.color
3. Kenapa prod.details.color bisa error?
Misalnya kita sedang melakukan loop:
for (const prod of products) {
console.log(prod.details.color);
}
Iterasi pertama
prod adalah iPhone:
prod = {
name: "iPhone",
price: 1000,
details: {
color: "black"
}
};
Maka:
prod.details.color
menjadi:
prod
↓
details
↓
color
↓
"black"
Aman. ✅
Iterasi kedua
prod adalah T-Shirt:
prod
↓
details
↓
color
↓
"white"
Aman juga. ✅
Iterasi ketiga
prod adalah Book:
prod = {
name: "Book",
price: 15,
pages: 300,
author: "John Smith"
};
Tidak ada:
details
Maka:
prod.details
menghasilkan:
undefined
Kemudian JavaScript mencoba melakukan:
undefined.color
Nah, ini yang menyebabkan error:
Cannot read properties of undefined
Visualnya:
prod
↓
details
↓
undefined
↓
.color
↓
💥 ERROR
4. Di sinilah Optional Chaining berguna
Kita ubah:
prod.details.color
menjadi:
prod.details?.color
Perhatikan ? dan .:
details?.color
^^
Artinya:
“Coba akses
color, tetapi hanya kalaudetailsbukannullatauundefined.”
Jadi ketika:
prod.details
berisi object:
{
color: "black"
}
maka:
prod.details?.color
akan dilanjutkan:
details
↓
object
↓
color
↓
"black"
Tetapi kalau:
prod.details
adalah:
undefined
maka:
details
↓
undefined
↓
STOP 🛑
↓
undefined
Tidak mencoba:
undefined.color
Jadi tidak terjadi error.
5. Cara membaca ?.
Kalau kamu melihat:
prod.details?.color
bacanya jangan:
“details tanda tanya titik color.”
Lebih mudah dibaca sebagai:
“Kalau
detailsada, ambilcolor. Kalaudetailstidak ada, hasilnyaundefined.”
Atau:
Apakah details ada?
↓
┌───┴───┐
YA TIDAK
↓ ↓
color undefined
6. Perhatikan: ?. mengecek null DAN undefined
Optional chaining bekerja ketika nilai yang dicek adalah:
null
atau:
undefined
Contoh:
const user = null;
console.log(user?.name);
Hasil:
undefined
Tidak error.
Begitu juga:
const user = undefined;
console.log(user?.name);
Hasil:
undefined
7. ?. bukan mengecek semua falsy value
Ini sangat penting karena sebelumnya kita belajar ??.
Optional chaining tidak berarti:
“Kalau nilainya falsy, berhenti.”
Yang dicek hanya:
null
undefined
Misalnya:
const user = {
name: ""
};
console.log(user?.name);
Hasil:
""
Bukan undefined.
Begitu juga:
const user = {
age: 0
};
console.log(user?.age);
Hasil:
0
Dan:
const user = {
isActive: false
};
console.log(user?.isActive);
Hasil:
false
Jadi:
null → berhenti
undefined → berhenti
"" → lanjut
0 → lanjut
false → lanjut
8. Bedakan “property tidak ada” dengan “parent object tidak ada”
Ini konsep yang sangat penting.
Misalnya:
const user = {
name: "John"
};
Kita melakukan:
console.log(user.age);
Tidak error.
Hasilnya:
undefined
Karena user ada, hanya property age yang tidak ada.
Visual:
user
↓
age tidak ada
↓
undefined
Tetapi:
const user = undefined;
console.log(user.age);
Ini error.
Karena:
user
↓
undefined
↓
undefined.age
↓
💥 ERROR
Optional chaining mengatasi masalah kedua:
console.log(user?.age);
hasil:
undefined
9. Optional Chaining pada nested object
Ini tempat Optional Chaining semakin terasa manfaatnya.
Misalnya:
const user = {
name: "John",
address: {
city: "Jakarta"
}
};
Kita bisa:
console.log(user.address.city);
Tetapi bagaimana kalau address tidak selalu ada?
const user = {
name: "John"
};
Kalau:
user.address.city
bisa error.
Kita bisa:
user.address?.city
Sekarang aman.
10. Kalau nested-nya lebih dalam?
Misalnya:
const user = {
profile: {
address: {
city: "Jakarta"
}
}
};
Kita bisa menulis:
user.profile?.address?.city
Artinya:
user
↓
profile ada?
↓
YA
↓
address ada?
↓
YA
↓
city
↓
"Jakarta"
Kalau profile tidak ada:
user
↓
profile
↓
undefined
↓
STOP
↓
undefined
Kalau profile ada tetapi address tidak ada:
user
↓
profile
↓
address
↓
undefined
↓
STOP
↓
undefined
11. Tapi perhatikan posisi ?.
Ini penting.
Misalnya:
user.profile?.address.city
Di sini kita hanya memberi optional chaining pada profile.
Artinya:
user.profile?.address
aman kalau profile null/undefined.
Tetapi kalau address bisa null/undefined, kita masih bisa mengalami masalah ketika .city dievaluasi.
Kalau address juga mungkin tidak ada, lebih aman:
user.profile?.address?.city
Jadi kita memberikan ?. pada setiap bagian yang memang mungkin null atau undefined.
12. Optional Chaining pada function/method
Optional chaining bukan hanya untuk property.
Kita juga bisa menggunakannya untuk memanggil function yang mungkin tidak tersedia.
Misalnya:
const user = {
greet() {
console.log("Hello");
}
};
Kita bisa:
user.greet?.();
Artinya:
“Kalau
greetmerupakan function yang tersedia, panggil. Kalau tidak ada, jangan error.”
Contoh:
const user = {};
user.greet?.();
Tidak error.
Hasilnya tidak ada apa-apa.
Ini berguna ketika sebuah function/method bersifat opsional.
13. Optional Chaining pada array
Ada bentuk lain:
?.[]
Misalnya:
const users = undefined;
console.log(users?.[0]);
Hasil:
undefined
Tanpa optional chaining:
users[0];
akan error karena users adalah undefined.
14. Contoh lengkap dengan data produk
Sekarang kita buat contoh seperti lecture:
const products = [
{
name: "iPhone",
price: 1000,
details: {
color: "black",
ram: "8GB"
}
},
{
name: "T-Shirt",
price: 20,
details: {
color: "white",
size: "L"
}
},
{
name: "Book",
price: 15,
pages: 300,
author: "John Smith"
}
];
for (const prod of products) {
console.log("Product:", prod.name);
console.log("Price:", prod.price);
console.log("Color:", prod.details?.color);
console.log("----------------");
}
Hasilnya kira-kira:
Product: iPhone
Price: 1000
Color: black
----------------
Product: T-Shirt
Price: 20
Color: white
----------------
Product: Book
Price: 15
Color: undefined
----------------
Perhatikan Book.
prod.details
adalah:
undefined
Tetapi:
prod.details?.color
tidak menyebabkan error.
Hasilnya:
undefined
15. Optional Chaining + Nullish Coalescing
Nah, ini menarik karena kita baru saja belajar ??.
Optional chaining sering sekali dikombinasikan dengan nullish coalescing.
Misalnya:
const color = prod.details?.color ?? "No color";
Cara kerjanya:
prod.details
↓
ada?
/ \
YES NO
↓ ↓
color undefined
↓ ↓
└───┬─┘
↓
??
↓
"No color"
Contoh:
const products = [
{
name: "iPhone",
details: {
color: "black"
}
},
{
name: "Book"
}
];
for (const prod of products) {
const color = prod.details?.color ?? "No color";
console.log(color);
}
Hasil:
black
No color
Kenapa?
iPhone
prod.details?.color
menghasilkan:
"black"
Kemudian:
"black" ?? "No color"
tetap:
"black"
Book
prod.details?.color
menghasilkan:
undefined
Kemudian:
undefined ?? "No color"
menghasilkan:
"No color"
Ini kombinasi yang sangat umum:
object?.property ?? defaultValue
Artinya:
“Kalau object/property ada, gunakan nilainya. Kalau tidak ada, gunakan default.”
16. Optional Chaining vs Nullish Coalescing
Karena kita baru belajar ??, jangan sampai tertukar.
Optional Chaining ?.
Tujuannya:
Mengakses sesuatu dengan aman.
user.address?.city
Artinya:
Kalau
addressada, aksescity.
Nullish Coalescing ??
Tujuannya:
Memberikan nilai default kalau hasilnya
nullatauundefined.
userName ?? "Guest"
Artinya:
Kalau
userNamenull/undefined, gunakan"Guest".
Digabungkan
user.address?.city ?? "Unknown"
Artinya:
“Kalau
addressada, ambilcity. Kalau hasil akhirnya null/undefined, gunakan"Unknown".”
17. Bedakan ?. dengan .
Ini juga perlu dibiasakan.
Normal:
user.name
Artinya:
Saya yakin
userada, jadi aksesname.
Optional:
user?.name
Artinya:
usermungkin ada, mungkin tidak. Kalau ada, ambilname. Kalau tidak, hasilkanundefined.
Visual:
user.name
↓
user HARUS ada
↓
kalau undefined → ERROR
user?.name
↓
user mungkin tidak ada
↓
kalau null/undefined → undefined
18. Kenapa TypeScript sangat menyukai Optional Chaining?
Ini berkaitan dengan strictNullChecks yang kita pelajari sebelumnya.
Misalnya:
const button = document.getElementById("submit");
TypeScript tahu bahwa hasilnya bisa:
HTMLElement
atau
null
Karena element dengan ID tersebut mungkin tidak ditemukan.
Kalau:
button.addEventListener("click", () => {
console.log("Clicked");
});
TypeScript bisa mengeluh:
button is possibly null
Karena TypeScript berpikir:
“Bagaimana kalau element-nya tidak ditemukan?”
Kita bisa melakukan pengecekan:
if (button) {
button.addEventListener("click", () => {
console.log("Clicked");
});
}
Atau dalam situasi tertentu, menggunakan optional chaining:
button?.addEventListener("click", () => {
console.log("Clicked");
});
Artinya:
Kalau
buttonada, jalankanaddEventListener. Kalaubuttonnull, jangan lakukan apa-apa.
19. Optional Chaining menghindari “Cannot read properties of undefined”
Error seperti ini sangat umum:
Cannot read properties of undefined
Biasanya terjadi karena kita melakukan:
something.property
padahal:
something === undefined
Contoh:
user.profile.name
Kalau:
user.profile === undefined
maka:
undefined.name
💥 Error.
Dengan:
user.profile?.name
menjadi:
undefined
dan program tetap berjalan.
20. Tetapi Optional Chaining bukan berarti “semua error hilang”
Ini juga penting.
Misalnya:
const user = {
profile: null
};
console.log(user.profile?.name);
Aman.
Tapi kalau kita melakukan kesalahan lain, misalnya:
user.profile?.name.toUpperCase()
perlu diperhatikan bagian mana yang memang mungkin nullish.
Lebih aman jika hasil name juga mungkin null/undefined:
user.profile?.name?.toUpperCase()
Jadi:
user
↓
profile?. ← aman
↓
name?. ← aman
↓
toUpperCase()
Optional chaining harus ditempatkan pada titik yang memang membutuhkan pengecekan.
21. Jangan menggunakan ?. secara berlebihan
Optional chaining memang nyaman, tetapi bukan berarti semua property harus diberi ?..
Misalnya:
user?.name?.firstName?.length
padahal kita sebenarnya tahu user, name, dan firstName selalu ada.
Kode seperti ini justru bisa menyembunyikan masalah data.
Gunakan ?. ketika memang:
Nilai tersebut secara logis mungkin
nullatauundefined.
Contohnya:
user.profile?.avatar
Kalau profile memang optional, masuk akal.
22. Analogi sederhana
Bayangkan kamu ingin masuk ke sebuah rumah:
Rumah → Kamar → Lemari → Barang
Normal:
house.room.cabinet.item
Kamu mengasumsikan:
Rumah ada
↓
Kamar ada
↓
Lemari ada
↓
Barang ada
Tapi bagaimana kalau kamar belum ada?
Dengan normal .:
Rumah
↓
Kamar
↓
❌ tidak ada
↓
.cabinet
↓
💥 ERROR
Optional chaining:
house.room?.cabinet?.item
berarti:
“Kalau kamar ada, lanjut. Kalau tidak ada, berhenti dengan aman.”
23. Hubungan dengan materi sebelumnya
Sekarang sebenarnya beberapa operator yang kita pelajari mulai saling terhubung.
||
value || "default"
Gunakan default kalau
valuefalsy.
??
value ?? "default"
Gunakan default kalau
valuenull/undefined.
?.
object?.property
Akses property dengan aman kalau
objectmungkin null/undefined.
Kombinasi
object?.property ?? "default"
Akses property dengan aman, lalu gunakan default kalau hasilnya
null/undefined.
Ini pola yang sangat sering kamu temui di TypeScript modern.
24. Cheat Sheet
| Syntax | Fungsi |
|---|---|
user.name | akses property biasa |
user?.name | akses name jika user ada |
user.address?.city | akses city jika address ada |
user.profile?.address?.city | akses nested object dengan aman |
user.greet?.() | panggil function jika tersedia |
users?.[0] | akses index jika array ada |
value ?? "default" | default jika null/undefined |
user?.name ?? "Guest" | akses aman + default |
25. Visual besar: cara kerja Optional Chaining
Ingat pola ini:
user?.profile?.address?.city
│
▼
user ada?
/ \
tidak ya
│ │
▼ ▼
undefined profile?
/ \
tidak ya
│ │
▼ ▼
undefined address?
/ \
tidak ya
│ │
▼ ▼
undefined city
│
▼
hasil
Jadi Optional Chaining seperti penjaga di setiap pintu.
Kalau object yang diperlukan ternyata tidak ada:
“Oke, berhenti di sini. Jangan lanjut supaya tidak error.”
🧠 Kesimpulan paling penting
Kalau kamu hanya ingin mengingat beberapa hal dari lecture ini, ingat 4 poin:
1. ?. = Optional Chaining
object?.property
Artinya:
“Kalau object-nya ada, akses property. Kalau
null/undefined, hasilnyaundefined.”
2. ?. hanya peduli null dan undefined
null → stop
undefined → stop
0 → lanjut
"" → lanjut
false → lanjut
3. Optional Chaining mencegah error seperti:
Cannot read properties of undefined
Contoh:
user.profile?.name
lebih aman daripada:
user.profile.name
jika profile memang bisa tidak ada.
4. ?. + ?? adalah kombinasi yang sangat berguna
const city = user.address?.city ?? "Unknown";
Bacanya:
“Kalau
addressada, ambilcity. Kalau tidak ada atau hasilnyanull/undefined, gunakan'Unknown'.”
Dan ini adalah mental model yang bagus untuk dibawa ke materi berikutnya:
?. → "AMAN NGGAK kalau aku akses ini?"
?? → "KALAU TIDAK ADA, pakai nilai apa?"
Jadi:
user?.profile?.name ?? "Guest"
bisa dibaca seperti percakapan:
“Kalau user ada, cek profile. Kalau profile ada, ambil name. Kalau pada akhirnya tidak ada name, pakai
'Guest'.”