Masukkan Password
26 Opsi Kompiler Pengecekan Tipe
Lecture ini membahas Type Checking Compiler Options di tsconfig.json.
Kalau lecture sebelumnya banyak membahas:
- file mana yang di-compile,
- output disimpan di mana,
- JavaScript versi berapa,
- apakah output dibuat,
maka lecture ini mulai masuk ke pertanyaan:
“Seberapa ketat TypeScript harus memeriksa code kita?”
Option utama yang dibahas adalah:
strictnoImplicitAnystrictNullChecksstrictBindCallApplyalwaysStrict
Yang paling penting untuk dipahami adalah strict, karena strict: true pada dasarnya mengaktifkan banyak pemeriksaan ketat sekaligus.
1. Apa Itu Type Checking?
Sebelum masuk ke option, kita pahami dulu konsepnya.
Misalnya kita menulis:
function sum(num1: number, num2: number): number {
return num1 + num2;
}
Kemudian:
sum(10, "20");
TypeScript akan mengatakan:
❌ Argument of type 'string' is not assignable to parameter of type 'number'.
Kenapa?
Karena kita sudah mengatakan:
num1: number
num2: number
Tetapi kita memberikan:
"20" // string
Jadi TypeScript melakukan:
SOURCE CODE
↓
TYPE CHECKING
↓
Ada masalah?
/ \
YES NO
↓ ↓
ERROR OK
Nah, type checking compiler options menentukan seberapa ketat proses tersebut.
2. strict
Ini adalah option yang paling penting:
{
"compilerOptions": {
"strict": true
}
}
Artinya:
Aktifkan pemeriksaan TypeScript secara ketat.
Ketika:
"strict": true
TypeScript akan mengaktifkan berbagai strict type-checking options yang relevan, termasuk beberapa option seperti:
noImplicitAny
strictNullChecks
strictBindCallApply
...
Jadi daripada kita menulis:
{
"compilerOptions": {
"noImplicitAny": true,
"strictNullChecks": true,
"strictBindCallApply": true,
...
}
}
satu per satu, kita bisa menggunakan:
{
"compilerOptions": {
"strict": true
}
}
3. Analogi strict
Bayangkan TypeScript seperti satpam di sebuah gedung.
Kalau:
strict = false
satpamnya agak santai:
“Ya sudah, masuk saja.”
Kalau:
strict = true
satpamnya lebih ketat:
“ID kamu mana?” “Ini datanya valid?” “Kamu yakin nilainya bukan
null?” “Parameter ini tipenya apa?” “Function ini benar-benar cocok?”
Jadi:
strict: true
↓
TypeScript lebih ketat
↓
lebih banyak potensi error ditemukan
↓
lebih banyak masalah bisa ditemukan
SEBELUM program dijalankan
Ini justru biasanya bagus untuk project TypeScript.
4. Apakah strict: true Selalu Harus Digunakan?
Untuk project TypeScript modern, umumnya strict checking sangat disarankan, karena tujuan TypeScript memang membantu menemukan masalah lebih awal.
Tetapi lecture juga menjelaskan bahwa kita bisa saja tidak ingin semua strict checking.
Misalnya:
{
"compilerOptions": {
"strict": false,
"noImplicitAny": true,
"strictNullChecks": false
}
}
Kita bisa mengatur pemeriksaan secara lebih spesifik.
Jadi ada dua pendekatan:
Pendekatan 1 — Aktifkan semuanya
"strict": true
Pendekatan 2 — Atur satu per satu
"strict": false,
"noImplicitAny": true,
"strictNullChecks": true
Untuk belajar, memahami option satu per satu tetap penting supaya kita tahu apa yang sebenarnya dilakukan strict.
5. noImplicitAny
Sekarang kita masuk ke option pertama.
"noImplicitAny": true
Ini berkaitan dengan implicit any.
6. Apa Itu Implicit any?
Kita sudah tahu any:
let value: any;
Artinya:
TypeScript membolehkan
valuememiliki tipe apa pun.
Tetapi ada perbedaan antara:
Explicit any
Kita sendiri menulis:
let value: any;
dengan:
Implicit any
TypeScript tidak mendapatkan informasi tipe, sehingga parameter bisa dianggap any.
Contohnya:
function sum(num1, num2) {
return num1 + num2;
}
Kita tidak memberikan tipe:
num1
num2
Dalam kondisi tertentu, TypeScript akan menganggap parameter tersebut sebagai any.
7. Kenapa any di Parameter Bisa Berbahaya?
Misalnya:
function sum(num1, num2) {
return num1 + num2;
}
Kita mungkin bermaksud:
num1 → number
num2 → number
Tetapi karena tidak diberi tipe, kita kehilangan informasi tersebut.
Kita bisa saja memanggil:
sum(10, 20);
atau:
sum("Hello", "World");
atau bahkan:
sum(true, {});
TypeScript tidak bisa melakukan pengecekan seketat kalau kita menulis:
function sum(num1: number, num2: number): number {
return num1 + num2;
}
8. noImplicitAny: true
Kalau kita menggunakan:
"noImplicitAny": true
TypeScript mengatakan:
“Jangan biarkan parameter mendapatkan
anysecara diam-diam. Kalau saya tidak tahu tipenya, kamu harus menjelaskannya.”
Misalnya:
function sum(num1, num2) {
return num1 + num2;
}
TypeScript akan memberikan error.
Kurang lebih:
Parameter 'num1' implicitly has an 'any' type.
Parameter 'num2' implicitly has an 'any' type.
Solusinya:
function sum(num1: number, num2: number) {
return num1 + num2;
}
Sekarang TypeScript tahu:
num1 → number
num2 → number
9. Kenapa Namanya noImplicitAny?
Pecah namanya:
no + implicit + any
Artinya:
no
↓
jangan
implicit
↓
secara otomatis/tidak dinyatakan secara eksplisit
any
↓
tipe any
Jadi:
“Jangan izinkan
anyyang muncul secara implicit.”
10. Explicit any vs Implicit any
Ini penting.
Explicit any
let value: any;
Kita secara sadar menulis any.
Implicit any
function test(value) {
}
Kita tidak menulis tipe.
TypeScript berpotensi menyimpulkan:
value → any
Dengan:
"noImplicitAny": true
yang menjadi masalah adalah implicit any, terutama pada parameter.
11. Apakah noImplicitAny Memeriksa Semua Variable?
Tidak persis seperti itu.
Lecture memberikan contoh:
let value;
dan menjelaskan bahwa noImplicitAny terutama berhubungan dengan parameter yang secara implicit menjadi any, bukan sekadar setiap variable yang tidak diberi annotation.
Ini penting karena:
"noImplicitAny": true
jangan dipahami sebagai:
“Semua variable wajib diberi type annotation.”
Bukan begitu.
TypeScript masih memiliki type inference.
Contoh:
let name = "John";
TypeScript bisa mengetahui:
name → string
Kita tidak perlu:
let name: string = "John";
Jadi noImplicitAny bukan berarti:
“Semua variable harus ditulis tipenya.”
Lebih tepat:
“Jangan biarkan TypeScript diam-diam memberikan
anypada situasi yang seharusnya kita jelaskan, terutama parameter.”
12. strictNullChecks
Option berikutnya:
"strictNullChecks": true
Ini berhubungan dengan:
null
undefined
dan kemungkinan sebuah nilai memiliki null.
13. Kenapa null Bisa Berbahaya?
Misalnya kita mengambil element dari DOM:
const button = document.getElementById("btn");
TypeScript mengetahui bahwa:
document.getElementById(...)
bisa menghasilkan:
HTMLElement
atau:
null
Kenapa bisa null?
Karena mungkin element dengan ID:
btn
tidak ada di HTML.
Misalnya HTML:
<button id="submit">Submit</button>
Tetapi kita mencari:
document.getElementById("btn");
Tidak ada id="btn".
Maka hasilnya:
null
14. Masalahnya Kalau Langsung Menggunakan Method
Misalnya:
const button = document.getElementById("btn");
button.addEventListener("click", () => {
console.log("Clicked");
});
TypeScript berpikir:
button
↓
mungkin HTMLElement
mungkin null
Kalau ternyata:
button = null
maka:
button.addEventListener(...)
akan bermasalah saat runtime.
Kurang lebih:
Cannot read properties of null
15. strictNullChecks Membantu Menemukan Masalah Ini
Dengan:
"strictNullChecks": true
TypeScript mengatakan:
“Tunggu, nilai ini mungkin
null. Jangan langsung digunakan sebelum kamu memastikan nilainya ada.”
Ini sangat bagus karena error bisa ditemukan saat compile, bukan ketika aplikasi sudah berjalan.
16. Cara Menanganinya: Check Null
Misalnya:
const button = document.getElementById("btn");
if (button) {
button.addEventListener("click", () => {
console.log("Clicked");
});
}
Sekarang TypeScript tahu:
if (button)
↓
button tidak null di dalam blok
Ini disebut:
type narrowing
Kita mempersempit kemungkinan tipe berdasarkan pengecekan.
17. Bagaimana dengan !?
Lecture juga menggunakan:
const button = document.getElementById("btn")!;
Tanda:
!
di sini disebut non-null assertion operator.
Kita seperti mengatakan kepada TypeScript:
“Saya sebagai developer yakin bahwa hasilnya tidak akan
null.”
Sehingga:
const button = document.getElementById("btn")!;
TypeScript tidak lagi memperlakukan hasil tersebut sebagai kemungkinan null.
Kemudian:
button.addEventListener(...);
tidak dipermasalahkan karena kita sudah memberi assertion tersebut.
18. Tapi Hati-Hati dengan !
! tidak membuat nilai menjadi tidak-null secara magic.
Misalnya ternyata element memang tidak ada:
const button = document.getElementById("btn")!;
maka runtime tetap bisa mendapatkan:
null
Jadi ! hanya memberi tahu TypeScript:
“Percayalah kepada saya.”
Bukan:
“Ubah null menjadi object.”
Karena itu, kalau kita tidak benar-benar yakin, lebih aman melakukan check:
if (button) {
...
}
19. strictNullChecks Secara Mental
Bayangkan TypeScript berkata:
“Apakah nilai ini bisa null?”
│
├── YA → hati-hati!
│
└── TIDAK → silakan gunakan
Jadi:
strictNullChecks
↓
mendeteksi kemungkinan null/undefined
↓
mencegah penggunaan yang berpotensi menyebabkan
runtime error
20. strictBindCallApply
Ini adalah option yang sedikit lebih advanced.
"strictBindCallApply": true
Option ini berkaitan dengan:
bind()
call()
apply()
yang merupakan method JavaScript untuk memanggil function atau mengatur nilai this.
Lecture menggunakan bind() sebagai contoh.
21. Sedikit Review bind()
Misalnya:
function clickHandler(message: string) {
console.log(message);
}
Function ini membutuhkan:
message → string
Kalau kita memanggil langsung:
clickHandler("Button is clicked");
jelas kita memberikan string.
Tetapi kita juga bisa menggunakan:
const handler = clickHandler.bind(null, "Button is clicked");
bind() menghasilkan function baru.
Kemudian:
handler();
akan menjalankan function dengan message yang sudah di-bind.
22. Kenapa strictBindCallApply Dibutuhkan?
TypeScript ingin memastikan bahwa argument yang kita berikan kepada:
bind()
call()
apply()
sesuai dengan function aslinya.
Misalnya:
function clickHandler(message: string) {
console.log(message);
}
Kita seharusnya memberikan:
clickHandler.bind(null, "Button is clicked");
Karena:
message → string
Tetapi kalau kita tidak memberikan message:
clickHandler.bind(null);
dengan strict checking aktif, TypeScript bisa mendeteksi bahwa function tersebut masih membutuhkan argument.
23. Kenapa null Ada di bind()?
Ini juga sempat membingungkan di lecture.
Syntax:
function.bind(thisArg, arg1, arg2, ...)
Argument pertama adalah:
thisArg
yaitu nilai yang akan digunakan sebagai:
this
di dalam function.
Contohnya:
function clickHandler(message: string) {
console.log(message);
}
Di function tersebut kita tidak menggunakan:
this
Jadi lecture menggunakan:
clickHandler.bind(null, "Button is clicked");
null di sini adalah nilai untuk this.
Sedangkan:
"Button is clicked"
adalah argument untuk:
message
Jadi:
bind(
null, ← thisArg
"Button is clicked" ← message
)
24. Kalau strictBindCallApply Aktif
Misalnya:
function clickHandler(message: string) {
console.log(message);
}
const handler = clickHandler.bind(null);
TypeScript akan lebih ketat dalam memeriksa penggunaan bind().
Jika argument yang dibutuhkan tidak diberikan sesuai signature, TypeScript bisa memberikan error.
Kalau kita memberikan:
const handler = clickHandler.bind(
null,
"Button is clicked"
);
maka sesuai:
clickHandler
↓
(message: string)
↓
bind(...)
↓
message diberikan string
↓
✅ valid
25. call() dan apply() Juga Terpengaruh
Bukan hanya:
bind()
tetapi juga:
call()
apply()
Contoh sederhana:
function greet(message: string) {
console.log(message);
}
Dengan strict checking, TypeScript akan berusaha memastikan argument yang diberikan melalui:
greet.call(...);
greet.apply(...);
greet.bind(...);
sesuai dengan function signature.
Jadi nama option-nya:
strictBindCallApply
bisa dibaca:
strict
↓
bind
call
apply
26. alwaysStrict
Sekarang option terakhir dari lecture:
"alwaysStrict": true
Ini agak berbeda dari tiga option sebelumnya.
alwaysStrict berkaitan dengan JavaScript strict mode.
TypeScript dapat menghasilkan JavaScript dengan:
"use strict";
di bagian awal file.
27. Apa Itu JavaScript Strict Mode?
JavaScript memiliki mode yang disebut:
Strict Mode
Biasanya ditandai dengan:
"use strict";
Misalnya output:
"use strict";
function greet(name) {
console.log("Hello " + name);
}
Strict mode membuat beberapa aturan JavaScript menjadi lebih ketat dan membantu mencegah perilaku tertentu yang rawan error.
28. alwaysStrict: true
Dengan:
"alwaysStrict": true
TypeScript akan memastikan file JavaScript yang dihasilkan menggunakan strict mode, sehingga output bisa memiliki:
"use strict";
Contoh:
function greet(name: string) {
console.log("Hello " + name);
}
bisa menjadi:
"use strict";
function greet(name) {
console.log("Hello " + name);
}
29. Kalau alwaysStrict: false?
Kalau:
"alwaysStrict": false
TypeScript tidak memaksakan strict mode pada output dengan cara tersebut.
Sehingga output bisa menjadi:
function greet(name) {
console.log("Hello " + name);
}
tanpa:
"use strict";
30. Jangan Tertukar: strict vs alwaysStrict
Ini sangat penting.
Keduanya memiliki nama strict, tetapi konteksnya berbeda.
strict
"strict": true
berhubungan dengan:
TypeScript type checking
Contohnya:
noImplicitAny
strictNullChecks
strictBindCallApply
...
alwaysStrict
"alwaysStrict": true
berhubungan dengan:
JavaScript strict mode pada output/source parsing
Jadi:
strict
↓
TypeScript checking
alwaysStrict
↓
JavaScript "use strict"
Jangan menganggap:
strict = alwaysStrict
Mereka berbeda.
31. Kenapa strict: true Sangat Penting?
Mari kita lihat dari perspektif development.
Tanpa strict checking:
function processUser(user) {
console.log(user.name);
}
TypeScript mungkin kehilangan informasi penting karena parameter tidak memiliki tipe.
Dengan strict:
function processUser(user: User) {
console.log(user.name);
}
kita dipaksa membuat kontrak yang lebih jelas.
Contoh lain:
const button = document.getElementById("btn");
button.addEventListener(...);
Tanpa strict null checking, masalah potensial bisa lolos.
Dengan:
strictNullChecks
TypeScript mengatakan:
“Bagaimana kalau
buttonternyatanull?”
Kita dipaksa menangani kemungkinan tersebut.
Ini sebenarnya salah satu manfaat utama TypeScript:
menemukan masalah lebih awal, sebelum runtime.
32. Visualisasi strict
Anggap strict sebagai saklar utama:
strict: true
│
┌───────────┼───────────┐
│ │ │
▼ ▼ ▼
noImplicitAny strictNullChecks strictBindCallApply
│ │ │
▼ ▼ ▼
checking null safety function checking
Dan masih ada beberapa strict-related options lainnya yang tidak dibahas mendalam di lecture.
Jadi strict bukan satu jenis pemeriksaan saja.
33. Contoh tsconfig.json
Misalnya kita ingin project TypeScript yang cukup ketat:
{
"compilerOptions": {
"target": "ES2016",
"rootDir": "./src",
"outDir": "./dist",
"strict": true,
"noEmitOnError": true,
"removeComments": true
},
"include": ["src"]
}
Dengan ini kita bisa membayangkan:
include
↓
file mana yang diproses?
rootDir
↓
source root
strict
↓
type checking ketat
noEmitOnError
↓
kalau error → jangan output
removeComments
↓
hapus comment dari output
outDir
↓
output ke dist/
34. Kalau Kita Ingin Mengatur Strict Checking Satu per Satu
Misalnya kita tidak ingin:
"strict": true
tetapi ingin memilih sendiri:
{
"compilerOptions": {
"strict": false,
"noImplicitAny": true,
"strictNullChecks": true,
"strictBindCallApply": true
}
}
Sekarang kita sendiri yang memilih pemeriksaannya.
Namun perlu diingat:
Untuk option yang berada di bawah umbrella
strict, jikastrict: true, option tersebut secara umum ikut diaktifkan kecuali kita override secara eksplisit.
Misalnya:
{
"compilerOptions": {
"strict": true,
"strictNullChecks": false
}
}
Artinya kita meminta strict mode secara umum, tetapi secara eksplisit menonaktifkan strictNullChecks.
35. Hubungkan Semua Option
Sekarang kita punya:
strict
│
├── noImplicitAny
│ ↓
│ jangan biarkan parameter
│ implicit any
│
├── strictNullChecks
│ ↓
│ cek kemungkinan null/undefined
│
├── strictBindCallApply
│ ↓
│ cek bind/call/apply
│
└── strict-related checks lainnya
Sedangkan:
alwaysStrict
↓
JavaScript strict mode
↓
"use strict"
36. Perbandingan yang Sangat Penting
| Option | Fokus |
|---|---|
strict | Mengaktifkan strict type checking secara keseluruhan |
noImplicitAny | Mencegah implicit any pada situasi yang seharusnya bertipe |
strictNullChecks | Memeriksa kemungkinan null/undefined |
strictBindCallApply | Memeriksa argument pada bind, call, apply |
alwaysStrict | Menggunakan JavaScript strict mode |
37. Contoh Kesalahan yang Dicegah
noImplicitAny
function greet(name) {
console.log(name);
}
Dengan strict checking:
❌ name implicitly has an 'any' type
Solusi:
function greet(name: string) {
console.log(name);
}
strictNullChecks
const button = document.getElementById("btn");
button.addEventListener(...);
TypeScript:
❌ button mungkin null
Solusi:
if (button) {
button.addEventListener(...);
}
strictBindCallApply
function greet(message: string) {
console.log(message);
}
Kemudian menggunakan bind() tanpa argument yang dibutuhkan:
const handler = greet.bind(null);
Strict checking akan lebih ketat terhadap signature function tersebut.
alwaysStrict
Output JavaScript:
"use strict";
38. Mental Model Paling Mudah
Bayangkan TypeScript adalah guru yang memeriksa tugasmu.
strict
Guru menjadi sangat teliti.
noImplicitAny
Guru:
“Parameter ini tipenya apa?
Jangan bilang 'terserah'.”
strictNullChecks
Guru:
“Nilai ini mungkin null.
Kamu sudah memastikan belum?”
strictBindCallApply
Guru:
“Argument function ini sudah cocok
dengan bind/call/apply belum?”
alwaysStrict
Guru:
“JavaScript output kamu harus menggunakan
strict mode.”
39. Cheat Sheet
Kalau nanti lupa, cukup ingat ini:
strict
↓
AKTIFKAN TYPE CHECKING YANG LEBIH KETAT
noImplicitAny
↓
JANGAN DIAM-DIAM JADI any
strictNullChecks
↓
HATI-HATI DENGAN null / undefined
strictBindCallApply
↓
CEK bind(), call(), apply()
alwaysStrict
↓
JAVASCRIPT STRICT MODE
"use strict";
Dan perbedaan paling penting:
TypeScript checking
│
▼
strict
│
┌───────────┼────────────┐
▼ ▼ ▼
noImplicitAny strictNullChecks strictBindCallApply
JavaScript behavior
│
▼
alwaysStrict
│
▼
"use strict"
Kesimpulan utama
Kalau tsconfig.json adalah aturan kerja TypeScript Compiler, maka strict bisa dianggap sebagai saklar untuk membuat TypeScript jauh lebih ketat dalam menemukan potensi kesalahan.
Yang paling penting untuk kamu kuasai dari lecture ini adalah:
strict: true→ TypeScript melakukan strict type checking.
Lalu pahami beberapa pemeriksaan di dalamnya:
noImplicitAny→ jangan biarkan parameter menjadianysecara implicit.
strictNullChecks→ jangan anggap sebuah nilai pasti ada kalau sebenarnya bisanull/undefined.
strictBindCallApply→ pastikanbind,call, danapplydigunakan sesuai function signature.
Sedangkan:
alwaysStrict→ berkaitan dengan JavaScript strict mode ("use strict"), bukan strict type checking.