Masukkan Password
27 Pilihan Kompiler Kualitas Kode
Di lecture ini kita membahas 3 compiler options TypeScript yang membantu meningkatkan code quality, yaitu:
noUnusedLocalsnoUnusedParametersnoImplicitReturns
Ketiganya punya tujuan yang mirip: membantu TypeScript menemukan code yang kemungkinan tidak diperlukan atau berpotensi menimbulkan bug.
1. Gambaran Besar
Sebelum masuk satu per satu, bayangkan TypeScript sebagai code reviewer otomatis.
Tanpa option tambahan:
Kita menulis code
↓
TypeScript mengecek tipe
↓
Kalau tipe benar → kemungkinan besar aman
Dengan compiler options ini:
Kita menulis code
↓
TypeScript mengecek tipe
↓
TypeScript juga mengecek:
- Ada variable yang tidak digunakan?
- Ada parameter yang tidak digunakan?
- Ada jalur function yang lupa return?
↓
Code menjadi lebih bersih dan konsisten
Jadi options ini bukan sekadar soal “code bisa jalan atau tidak”, tetapi juga:
“Apakah code kita masuk akal dan tidak memiliki bagian yang tidak diperlukan?”
2. noUnusedLocals
Mari mulai dari yang pertama.
{
"compilerOptions": {
"noUnusedLocals": true
}
}
Artinya:
TypeScript akan memperingatkan/error ketika kita membuat local variable tetapi variable tersebut tidak pernah digunakan.
Apa itu local variable?
Local variable adalah variable yang dibuat di dalam scope tertentu, misalnya di dalam function.
Contoh:
function sum(num1: number, num2: number) {
const result = num1 + num2;
return num1 + num2;
}
Di sini:
const result = num1 + num2;
kita membuat variable result.
Tetapi kemudian:
return num1 + num2;
kita tidak pernah menggunakan result.
Jadi sebenarnya:
const result = num1 + num2;
tidak memberikan manfaat apa pun.
TypeScript akan memberi warning
Kalau:
{
"compilerOptions": {
"noUnusedLocals": true
}
}
TypeScript akan mendeteksi:
const result = num1 + num2;
dan mengatakan kira-kira:
'result' is declared but its value is never read.
Artinya:
“
resultsudah dibuat, tetapi nilainya tidak pernah dibaca/digunakan.”
Biasanya di VS Code akan muncul orange squiggly line.
3. Kenapa ini berguna?
Bayangkan kita punya function yang panjang:
function calculatePrice(price: number, tax: number) {
const discount = 100;
const taxAmount = price * tax;
const total = price + taxAmount;
return total;
}
Ternyata:
discount
tidak pernah digunakan.
Code tersebut sebenarnya bisa dibuat lebih bersih:
function calculatePrice(price: number, tax: number) {
const taxAmount = price * tax;
const total = price + taxAmount;
return total;
}
Jadi noUnusedLocals membantu kita menemukan variable yang kemungkinan merupakan sisa code atau kesalahan programmer.
4. Kenapa unused variable bisa menjadi masalah?
Kadang unused variable memang tidak menyebabkan program crash.
Tetapi dalam project besar, semakin banyak code yang tidak digunakan:
unused variable
unused function
unused import
dead code
semakin sulit project dipahami.
Contohnya:
function calculate() {
const price = 100;
const discount = 20;
const tax = 10;
const shipping = 15;
return price + tax;
}
Orang yang membaca code bisa bertanya:
“Discount digunakan tidak?”
“Shipping digunakan tidak?”
“Kenapa variable-variable ini dibuat?”
Dengan noUnusedLocals, TypeScript membantu menemukan hal seperti ini.
5. Local vs Global Variable
Ini bagian yang sangat penting dari lecture.
noUnusedLocals terutama berkaitan dengan local variables.
Contoh:
function sum(num1: number, num2: number) {
const result = num1 + num2;
return num1 + num2;
}
result adalah local variable karena berada di dalam function.
Sedangkan:
const data = 100;
function sum(num1: number, num2: number) {
return num1 + num2;
}
data berada di luar function, sehingga merupakan variable pada scope luar/global/module scope.
TypeScript tidak selalu menganggap variable tersebut tidak berguna hanya karena tidak dipakai di file itu.
Mengapa?
Karena bisa saja variable tersebut digunakan oleh bagian lain dari program, misalnya melalui module/export/import atau konteks project lainnya.
Jadi secara sederhana:
noUnusedLocals
↓
cek local variable
↓
"Apakah variable ini dibuat tapi tidak digunakan?"
↓
Ya → beri warning/error
6. Cara memperbaikinya
Misalnya:
function sum(num1: number, num2: number) {
const result = num1 + num2;
return num1 + num2;
}
Ada dua kemungkinan.
Pilihan 1 — Gunakan variable-nya
function sum(num1: number, num2: number) {
const result = num1 + num2;
return result;
}
Sekarang result digunakan.
Pilihan 2 — Hapus variable-nya
Kalau memang tidak dibutuhkan:
function sum(num1: number, num2: number) {
return num1 + num2;
}
Biasanya ini lebih baik daripada membuat variable yang tidak diperlukan.
7. noUnusedParameters
Sekarang option kedua:
{
"compilerOptions": {
"noUnusedParameters": true
}
}
Ini hampir sama dengan noUnusedLocals.
Bedanya:
noUnusedLocals→ mengecek variable lokal
noUnusedParameters→ mengecek parameter function
Apa itu parameter?
Contoh:
function sum(num1: number, num2: number) {
return num1 + num2;
}
num1 dan num2 adalah parameter.
Secara sederhana:
function sum(num1, num2)
↑ ↑
parameter
8. Contoh unused parameter
Misalnya kita membuat:
function sum(
num1: number,
num2: number,
message: string
) {
return num1 + num2;
}
Parameter:
message
tidak pernah digunakan.
Kita tidak melakukan:
console.log(message);
atau:
return message;
Jadi message sebenarnya tidak diperlukan.
Dengan:
"noUnusedParameters": true
TypeScript akan memberikan warning:
'message' is declared but its value is never read.
9. Kenapa parameter seperti ini bisa terjadi?
Ini cukup sering terjadi ketika function berkembang.
Awalnya:
function sum(num1: number, num2: number) {
return num1 + num2;
}
Kemudian seseorang mungkin menambahkan parameter:
function sum(
num1: number,
num2: number,
message: string
) {
return num1 + num2;
}
Tapi ternyata message tidak pernah digunakan.
Akibatnya caller harus memberikan argument tambahan:
sum(10, 20, "hello");
padahal function tidak membutuhkan "hello" sama sekali.
Lebih bersih:
sum(10, 20);
10. noUnusedLocals vs noUnusedParameters
Ini wajib diingat.
| Option | Yang dicek |
|---|---|
noUnusedLocals | Local variable yang tidak digunakan |
noUnusedParameters | Parameter function yang tidak digunakan |
Contoh:
Local variable
function test() {
const data = 100;
return 200;
}
data → local variable
Maka:
noUnusedLocals
↓
mendeteksi
Parameter
function test(data: number) {
return 200;
}
data → parameter
Maka:
noUnusedParameters
↓
mendeteksi
11. noImplicitReturns
Sekarang kita masuk option ketiga:
{
"compilerOptions": {
"noImplicitReturns": true
}
}
Ini sedikit lebih penting untuk dipahami.
Artinya:
TypeScript akan memperingatkan ketika sebuah function memiliki beberapa jalur eksekusi, tetapi tidak semua jalur tersebut menghasilkan
return.
12. Apa maksudnya “code path”?
Bayangkan sebuah function memiliki percabangan:
function test(value: number) {
if (value > 0) {
return "positive";
} else {
console.log("not positive");
}
}
Ada dua kemungkinan jalur:
value
↓
value > 0?
/ \
YES NO
↓ ↓
return console.log()
"positive" ↓
selesai
Jalur pertama:
return "positive";
Ada return.
Jalur kedua:
console.log("not positive");
Tidak ada return.
Jadi tidak semua code path mengembalikan value.
13. Warning Not all code paths return a value
Dengan:
"noImplicitReturns": true
TypeScript akan mengatakan kira-kira:
Not all code paths return a value.
Artinya:
“Tidak semua jalur eksekusi function mengembalikan value.”
Ini sangat berguna karena kadang programmer tidak sadar bahwa ada satu kondisi yang tidak melakukan return.
14. Contoh dari lecture
Misalnya kita ingin function sum() hanya menerima angka positif.
function sum(num1: number, num2: number) {
if (num1 > 0 && num2 > 0) {
return num1 + num2;
} else {
console.log("Numbers must be greater than zero");
}
}
Mari kita lihat.
Kondisi pertama
Kalau:
num1 = 10
num2 = 20
maka:
num1 > 0 && num2 > 0
adalah true.
Function melakukan:
return num1 + num2;
hasil:
30
Kondisi kedua
Kalau:
num1 = -10
num2 = 20
kondisi:
num1 > 0 && num2 > 0
adalah false.
Maka masuk:
else {
console.log("Numbers must be greater than zero");
}
Function tidak melakukan return.
15. Masalahnya: return type menjadi tidak konsisten
Secara konsep function ini bisa menghasilkan:
jalur A → number
jalur B → tidak return value
Kalau function digunakan seperti:
const result = sum(10, -20);
apa isi result?
Tidak ada angka yang dikembalikan.
Secara runtime, function seperti ini pada akhirnya menghasilkan:
undefined
Jadi programmer mungkin mengharapkan:
number
tetapi ternyata bisa mendapatkan:
undefined
Ini bisa menjadi sumber bug.
16. noImplicitReturns membantu menemukan masalah ini
Dengan:
"noImplicitReturns": true
TypeScript mengatakan:
Not all code paths return a value.
Dengan kata lain:
“Hei, function ini kadang return value, kadang tidak. Coba periksa lagi.”
Ini bukan berarti TypeScript selalu mengatakan logic kita pasti salah.
Bisa saja memang kita sengaja membuat function seperti itu.
Tetapi option ini membuat kita secara eksplisit menyadari bahwa hal tersebut terjadi.
17. Bagaimana cara memperbaikinya?
Salah satu cara adalah memastikan semua jalur melakukan return.
Misalnya:
function sum(num1: number, num2: number) {
if (num1 > 0 && num2 > 0) {
return num1 + num2;
} else {
console.log("Numbers must be greater than zero");
return 0;
}
}
Sekarang:
num1 & num2 > 0
↓
return number
num1 atau num2 <= 0
↓
return 0
Semua jalur menghasilkan number.
18. Tapi hati-hati: return 0 punya arti
Jangan asal menambahkan:
return 0;
hanya supaya warning hilang.
Karena 0 mempunyai makna.
Misalnya:
function divide(a: number, b: number) {
if (b !== 0) {
return a / b;
}
return 0;
}
Di sini kita mengatakan:
Kalau pembagian tidak valid, hasilnya dianggap
0.
Padahal mungkin yang lebih benar adalah error:
function divide(a: number, b: number) {
if (b === 0) {
throw new Error("Cannot divide by zero");
}
return a / b;
}
Jadi tujuan noImplicitReturns bukan:
“Tambahkan return sembarang.”
Tetapi:
“Pastikan setiap kemungkinan jalur function sudah dipikirkan.”
Ini konsep yang jauh lebih penting.
19. Hubungan dengan return dan void
Ini juga perlu dibedakan.
Function seperti:
function printMessage(message: string): void {
console.log(message);
}
memang tidak mengembalikan value.
Itu normal.
noImplicitReturns terutama berguna ketika function memiliki jalur yang sebagian return value dan sebagian tidak.
Misalnya:
function getNumber(value: boolean): number {
if (value) {
return 100;
}
}
Ini bermasalah karena:
true → return 100
false → tidak return
Kalau function memang sengaja tidak mengembalikan value, biasanya lebih tepat menggunakan:
function doSomething(): void {
console.log("Hello");
}
daripada function yang kadang mengembalikan value dan kadang tidak.
20. Analogi sederhana
Bayangkan sebuah mesin.
noUnusedLocals
Kita memasukkan barang ke mesin:
Variable A
Variable B
Variable C
Tetapi:
Variable C tidak pernah digunakan
TypeScript berkata:
“Kenapa kamu membawa barang ini kalau tidak dipakai?”
noUnusedParameters
Function menerima:
input A
input B
input C
tetapi hanya menggunakan:
A + B
TypeScript berkata:
“Kalau C tidak digunakan, kenapa function meminta C?”
noImplicitReturns
Function memiliki beberapa jalan keluar:
START
↓
kondisi?
/ \
A B
↓ ↓
RETURN ????
TypeScript berkata:
“Jalan A sudah punya output. Jalan B bagaimana?”
21. Ketiga option jika digabungkan
Misalnya kita punya:
function calculate(
num1: number,
num2: number,
message: string
) {
const result = num1 + num2;
if (result > 0) {
return result;
}
}
Ada beberapa masalah:
Masalah 1
message
tidak digunakan.
→ noUnusedParameters
Masalah 2
result
sebenarnya digunakan, jadi tidak masalah.
Masalah 3
Kalau:
result <= 0
tidak ada return.
→ noImplicitReturns
22. Contoh code yang sudah diperbaiki
Kita bisa membuat:
function calculate(
num1: number,
num2: number
): number {
const result = num1 + num2;
if (result > 0) {
return result;
}
return 0;
}
Sekarang:
- Tidak ada parameter yang tidak digunakan.
resultdigunakan.- Semua code path memiliki
return. - Return value selalu
number.
Lebih jelas dan lebih mudah dipelihara.
23. Kenapa compiler option seperti ini penting?
Karena compiler bukan hanya untuk mencari error seperti:
let age: number = "hello";
Compiler juga bisa membantu menjaga kualitas code.
Tanpa pengecekan:
Code
├── variable tidak digunakan
├── parameter tidak digunakan
├── code path lupa return
└── dead/unnecessary code
Dengan options:
TypeScript
↓
lebih banyak masalah ditemukan
↓
sebelum program dijalankan
Inilah salah satu kekuatan TypeScript.
24. Warning vs Error
Di lecture ada bagian yang mengatakan warning di VS Code lalu ketika tsc dijalankan menjadi error.
Secara praktis, bedakan dua hal:
Di VS Code
Kita bisa melihat:
orange squiggly
yang terlihat seperti warning/diagnostic.
Saat compiler dijalankan
Misalnya:
tsc
TypeScript dapat menganggap diagnostic tersebut sebagai compile error, sehingga compilation bisa gagal, tergantung option dan konfigurasi project.
Jadi jangan hanya berpikir:
“Orange berarti tidak penting.”
Justru option seperti ini bisa membuat tsc gagal sehingga masalah harus diperbaiki sebelum menghasilkan output.
25. Hubungan dengan compiler options yang sudah kita pelajari
Sekarang kita sudah memiliki beberapa kelompok compiler options.
File mana yang dikompilasi?
include
exclude
files
Bagaimana JavaScript dibuat?
target
outDir
rootDir
API apa yang dikenali TypeScript?
lib
Bagaimana output/debugging?
sourceMap
declaration
declarationMap
Apakah JavaScript ikut diperiksa?
allowJs
checkJs
Seberapa ketat pengecekan?
strict
noImplicitAny
strictNullChecks
strictBindCallApply
alwaysStrict
Dan sekarang:
noUnusedLocals
noUnusedParameters
noImplicitReturns
yang lebih fokus kepada code quality.
26. Cheat Sheet
| Option | Fungsi sederhana |
|---|---|
noUnusedLocals | Cek local variable yang tidak digunakan |
noUnusedParameters | Cek parameter function yang tidak digunakan |
noImplicitReturns | Pastikan semua code path function memiliki return ketika memang mengembalikan value |
Contoh:
function test(value: number, message: string) {
const result = value * 2;
if (result > 0) {
return result;
}
}
Potensi masalah:
message
↓
tidak digunakan
↓
noUnusedParameters
dan:
result > 0
↓
return
result <= 0
↓
tidak return
↓
noImplicitReturns
27. Cara Mengingatnya
Gunakan kalimat sederhana ini:
noUnusedLocals
↓
"Variable lokal ini dipakai nggak?"
noUnusedParameters
↓
"Parameter ini dipakai nggak?"
noImplicitReturns
↓
"Semua jalan function punya return nggak?"
Atau lebih singkat:
LOCAL → dipakai?
PARAMETER → dipakai?
RETURN → semua jalur aman?
28. Mental Model Besar
Kalau digabung dengan materi sebelumnya:
TypeScript Compiler
│
┌────────────────┼────────────────┐
↓ ↓ ↓
File selection Output rules Code quality
│ │ │
include/exclude target strict
files rootDir noImplicitAny
outDir strictNullChecks
│
↓
noUnusedLocals
noUnusedParameters
noImplicitReturns
Jadi tiga option dari lecture ini bukan fitur TypeScript yang membuat program lebih cepat, melainkan fitur yang membuat kita lebih cepat menemukan code yang mencurigakan, tidak diperlukan, atau tidak konsisten.
Inti paling penting:
noUnusedLocalsmenjaga agar variable lokal yang tidak diperlukan tidak dibiarkan.
noUnusedParametersmenjaga agar function tidak meminta parameter yang sebenarnya tidak digunakan.
noImplicitReturnsmenjaga agar kita tidak lupa menangani return pada salah satu jalur function.
Kalau ketiganya digabung dengan strict: true, TypeScript bisa menjadi semacam code reviewer otomatis yang membantu menangkap banyak masalah sebelum code sampai dijalankan di browser.