Masukkan Password
65 Proyek Pelacak Pengeluaran: Tinjauan Umum
Lecture ini bukan mengajarkan syntax TypeScript baru secara mendalam, tetapi merupakan jembatan dari teori TypeScript ke project nyata.
Setelah sebelumnya kita belajar banyak konsep seperti Union Type, Literal Type, Type Guard, Type Assertion, Interface, Class, Generic, keyof, Utility Types, dan lain-lain, sekarang semua konsep itu akan dipakai dalam satu aplikasi nyata: Expense Tracker.
1. Gambaran Besar Lecture Ini
Sederhananya, instructor mengatakan:
βKita sudah belajar banyak teori TypeScript. Sekarang kita akan menggunakan teori tersebut untuk membuat aplikasi sungguhan.β
Aplikasi yang akan dibuat adalah:
π° Expense Tracking Application
Aplikasi untuk mencatat pemasukan dan pengeluaran.
Contohnya:
Total Balance: $15,270
Income:
+ YouTube Earnings $5,500
+ Salary $3,000
Expenses:
- Groceries $230
- Movie Ticket $50
User bisa:
- Menambahkan pemasukan (
credit) - Menambahkan pengeluaran (
debit) - Melihat total uang
- Menghapus transaksi
- Melihat detail transaksi
- UI otomatis berubah berdasarkan jenis transaksi
Dan semuanya akan dibuat menggunakan:
HTML
CSS
TypeScript
2. Kenapa Project Ini Penting?
Sebelumnya kita mungkin belajar seperti:
type ExpenseType = "credit" | "debit";
Kita tahu secara teori apa itu Union Type dan Literal Type.
Tapi pertanyaan yang lebih penting adalah:
βDalam project nyata, kapan saya menggunakan ini?β
Nah, project ini akan menjawab pertanyaan tersebut.
Misalnya:
Teori
Kita belajar:
type UserRole = "admin" | "user";
Project nyata
Kita punya:
type ExpenseType = "credit" | "debit";
Artinya TypeScript akan memastikan bahwa expense hanya boleh mempunyai dua tipe:
credit
debit
Tidak boleh:
"salary"
"food"
"random"
"abc"
Jadi kita mulai melihat hubungan:
Konsep TypeScript
β
Implementasi
β
Project nyata
β
Problem yang benar-benar terjadi
3. Apa Itu Expense Tracker?
Mari kita pahami aplikasi ini terlebih dahulu sebelum masuk ke TypeScript.
Ada dua jenis transaksi:
Credit
credit berarti uang masuk.
Contoh:
Salary
YouTube Earnings
Freelance Payment
Bonus
Misalnya:
YouTube Earnings = $5,500
Maka balance bertambah:
10000 + 5500 = 15500
Dan ditampilkan dengan warna hijau.
Debit
debit berarti uang keluar.
Contoh:
Groceries
Movie Ticket
Electricity
Internet
Rent
Misalnya:
Groceries = $230
Kalau balance awal:
10000
maka:
10000 - 230 = 9770
Jadi debit mengurangi total.
4. Bentuk Data Expense
Secara konsep, satu expense kemungkinan akan memiliki informasi seperti:
Expense
βββ type
βββ description
βββ amount
βββ date
Misalnya:
{
type: "debit",
description: "Groceries",
amount: 230,
date: ...
}
Atau:
{
type: "credit",
description: "YouTube Earnings",
amount: 5500,
date: ...
}
Ini nantinya akan menjadi salah satu objek penting dalam aplikasi.
5. Kenapa type Menggunakan Literal Type + Union?
Ini salah satu konsep TypeScript yang secara eksplisit disebut instructor.
Kemungkinan kita akan memiliki:
type ExpenseType = "credit" | "debit";
Mari kita pecah.
"credit" dan "debit"
Ini disebut Literal Types.
Bukan:
string
tetapi nilai yang sangat spesifik:
"credit"
atau:
"debit"
Kemudian:
|
adalah Union Type.
Jadi:
"credit" | "debit"
berarti:
Nilainya harus
"credit"ATAU"debit".
Contoh
let type: "credit" | "debit";
type = "credit"; // β
type = "debit"; // β
type = "salary"; // β
type = "food"; // β
type = "abc"; // β
Ini sangat berguna dalam aplikasi karena kita ingin mencegah data invalid.
6. Kenapa Tidak Cukup Menggunakan string?
Kita sebenarnya bisa saja menulis:
type: string;
Tapi masalahnya:
type = "credit";
type = "debit";
type = "something";
type = "hello";
Semuanya dianggap valid karena semuanya adalah string.
Padahal aplikasi kita hanya mengenal:
credit
debit
Maka lebih aman:
type: "credit" | "debit";
Ini contoh nyata bagaimana TypeScript memberikan type safety.
7. Flow Menambahkan Expense
Sekarang mari kita pahami alur ketika user menambahkan transaksi.
Misalnya user mengisi:
Type: Debit
Description: Groceries
Amount: 230
Kemudian klik:
Add Expense
Flow-nya kira-kira:
User mengisi form
β
Klik Add Expense
β
TypeScript menangkap event
β
Ambil nilai dari input
β
Buat object Expense
β
Simpan expense
β
Hitung total
β
Update UI
Jadi TypeScript menjadi semacam “otak” dari aplikasi.
8. DOM Akan Digunakan
Instructor juga mengatakan:
accessing the DOM element
Artinya TypeScript akan berinteraksi dengan HTML.
Misalnya HTML memiliki:
<input id="description">
Kemudian TypeScript mengambil element tersebut:
const description = document.querySelector("#description");
Atau bisa menggunakan:
const description =
document.querySelector("#description") as HTMLInputElement;
Nah, ini langsung berhubungan dengan materi yang sudah kita pelajari:
Type Assertion / Type Casting
Kita sebelumnya belajar:
const input =
document.querySelector("#name") as HTMLInputElement;
Karena TypeScript belum tentu tahu bahwa element tersebut adalah input.
Dengan assertion:
as HTMLInputElement
kita memberi tahu TypeScript:
“Saya yakin element ini adalah HTMLInputElement.”
Kemudian kita bisa menggunakan:
input.value
9. Project Ini Juga Menggunakan Class
Instructor juga mengatakan:
here we are creating a class
Artinya kita akan menggunakan konsep Object-Oriented Programming.
Misalnya nanti ada:
class ExpenseTracker {
...
}
Class tersebut bisa bertanggung jawab terhadap berbagai hal seperti:
ExpenseTracker
β
βββ menyimpan expenses
βββ menambahkan expense
βββ menghapus expense
βββ menghitung total
βββ menampilkan expense
βββ menampilkan detail expense
Ini adalah penerapan langsung materi:
OOP
β
Class
β
Object
β
Methods
β
Application
10. Kenapa Menggunakan Class?
Bayangkan semua logic kita tulis begitu saja:
let expenses = [];
function addExpense() {}
function deleteExpense() {}
function calculateTotal() {}
function showExpense() {}
function showTotal() {}
Bisa bekerja, tetapi ketika aplikasi semakin besar, semuanya bisa menjadi berantakan.
Dengan class, kita dapat mengelompokkan logic yang berkaitan:
class ExpenseTracker {
private expenses = [];
addExpense() {
// ...
}
deleteExpense() {
// ...
}
calculateTotal() {
// ...
}
}
Secara konsep:
Class menjadi tempat untuk mengorganisasi data dan behavior aplikasi.
11. Dynamic Content
Instructor juga menyebut:
generate some Dynamic contents and insert it in the DOM
Ini sangat penting.
Artinya daftar expense tidak ditulis manual di HTML.
Misalnya kita tidak ingin HTML seperti:
<div>Groceries - $230</div>
<div>Movie Ticket - $50</div>
<div>YouTube Earnings - $5500</div>
Karena datanya bisa berubah.
User bisa menambahkan:
Groceries
kemudian:
Movie Ticket
kemudian:
YouTube Earnings
Maka TypeScript harus membuat HTML tersebut secara dynamic.
Konsepnya:
Data
β
TypeScript
β
Generate HTML
β
Insert ke DOM
12. Contoh Dynamic Content
Misalnya kita punya:
const expense = {
description: "Groceries",
amount: 230
};
Kita bisa membuat HTML:
const html = `
<div>
<span>${expense.description}</span>
<span>${expense.amount}</span>
</div>
`;
Kemudian memasukkannya ke DOM.
Misalnya:
container.innerHTML += html;
Hasil akhirnya di browser:
Groceries $230
Jadi TypeScript bukan hanya menghitung data, tetapi juga mengubah tampilan aplikasi.
13. Credit dan Debit Memiliki UI Berbeda
Ini juga bagian menarik.
Instructor mengatakan:
if it is credit it will be displayed in green and right side
Sedangkan debit ditampilkan berbeda.
Jadi berdasarkan:
expense.type
kita bisa menentukan bagaimana UI ditampilkan.
Misalnya secara konsep:
if (expense.type === "credit") {
// tampilkan sebagai income
} else {
// tampilkan sebagai expense
}
Ini juga menggunakan konsep yang sudah kita pelajari:
Type Narrowing
Karena:
expense.type
memiliki type:
"credit" | "debit"
ketika kita melakukan:
if (expense.type === "credit")
TypeScript bisa mengetahui bahwa di dalam block tersebut:
expense.type
adalah:
"credit"
14. Menghitung Total
Ini adalah logic utama aplikasi.
Misalnya balance awal:
$10,000
Kemudian:
Debit: Groceries $230
Debit: Movie Ticket $50
Maka:
10000 - 230 - 50
hasil:
$9,720
Kemudian user mendapatkan:
Credit: YouTube Earnings $5,500
Maka:
9720 + 5500
hasil:
$15,220
Jadi secara konsep:
if (expense.type === "credit") {
total += expense.amount;
} else {
total -= expense.amount;
}
15. Kenapa Delete Expense Lebih Menarik?
Bagian delete sebenarnya membutuhkan pemikiran yang sedikit lebih hati-hati.
Misalnya sekarang:
Total = $10,000
Groceries = -$230
Maka:
Total = $9,770
Kemudian Groceries dihapus.
Apa yang harus terjadi?
Kita harus mengembalikan $230:
$9,770 + $230 = $10,000
Jadi:
Ketika menghapus debit
Total + amount
Sebaliknya, misalnya:
Total = $10,000
YouTube Earnings = +$5,500
Maka:
Total = $15,500
Kalau income tersebut dihapus:
$15,500 - $5,500
kembali:
$10,000
Jadi:
Ketika menghapus credit
Total - amount
16. Tabel Logic Expense
Supaya gampang diingat:
| Action | Credit | Debit |
|---|---|---|
| Add | + amount | - amount |
| Delete | - amount | + amount |
Perhatikan bahwa delete adalah kebalikan dari add.
Contoh:
ADD CREDIT
10000 + 500
= 10500
DELETE CREDIT
10500 - 500
= 10000
Sedangkan:
ADD DEBIT
10000 - 500
= 9500
DELETE DEBIT
9500 + 500
= 10000
17. Show Expense Details
Fitur berikutnya adalah ketika user mengklik sebuah expense.
Misalnya:
Groceries -$230
User klik item tersebut.
Aplikasi akan menampilkan:
Expense Details
Description: Groceries
Amount: $230
Date: September 6, 2026
Type: Debit
Jadi setiap expense kemungkinan memiliki informasi seperti:
{
type: "debit",
description: "Groceries",
amount: 230,
date: ...
}
Kemudian ketika user memilih expense tertentu, aplikasi mengambil object tersebut dan menampilkan detailnya.
18. Event Listener
Instructor juga menyebut:
we are handling the click event on this button element
dan:
addEventListener method
Ini adalah konsep JavaScript/DOM yang sangat penting.
Misalnya kita memiliki button:
<button id="add-expense">
Add Expense
</button>
Kemudian TypeScript:
button.addEventListener("click", () => {
// lakukan sesuatu
});
Artinya:
“Ketika button ini diklik, jalankan function ini.”
Flow-nya:
User klik button
β
Browser mendeteksi "click"
β
addEventListener bekerja
β
Callback function dijalankan
β
Expense dibuat
β
UI diperbarui
19. Apa Itu Event?
Event adalah sesuatu yang terjadi di browser.
Contohnya:
click
input
submit
change
keydown
mouseover
Untuk project ini yang paling penting adalah:
"click"
Misalnya:
button.addEventListener("click", addExpense);
Artinya:
button
β
mendengarkan
β
"click"
β
jalankan addExpense
20. showTotal() Function
Instructor juga menyebut:
show total function where we are displaying the total amount
Kemungkinan akan ada function seperti:
showTotal() {
// ...
}
Tugasnya adalah mengambil nilai total dan menampilkannya di header.
Misalnya total internal:
this.total = 9770;
Kemudian:
showTotal()
mengubah tampilan menjadi:
Total Expense: $9,770
Jadi kita bisa membayangkan ada dua bagian:
DATA / LOGIC
β
total = 9770
β
showTotal()
β
DOM
β
"Total: $9,770"
21. Konsep TypeScript yang Akan Dipakai
Ini bagian yang sangat penting dari lecture.
Instructor sebenarnya sedang memberi kita peta perjalanan untuk beberapa lecture berikutnya.
Konsep yang akan dipakai:
| Konsep | Penggunaan |
|---|---|
| Data Types | Menentukan tipe data expense |
| Literal Types | "credit" dan "debit" |
| Union Types | "credit" | "debit" |
| Type Assertion | Mengambil DOM element dengan tipe yang tepat |
| DOM | Mengakses dan memanipulasi HTML |
| Class | Membuat struktur Expense Tracker |
| OOP | Mengorganisasi logic aplikasi |
| Functions | Menjalankan berbagai operasi |
| Dynamic Content | Membuat UI berdasarkan data |
| Event Listener | Menangani klik user |
| Array | Menyimpan daftar expenses |
| Type Safety | Mencegah data invalid |
| Generics | Jika dibutuhkan pada struktur tertentu |
| Interface/Types | Mendefinisikan bentuk data |
Jadi project ini seperti laboratorium TypeScript.
22. Hubungan dengan Materi yang Sudah Kita Pelajari
Ini yang paling penting supaya pembelajaranmu nyambung.
Kita sudah belajar:
Union
"credit" | "debit"
Sekarang digunakan untuk:
expense.type
Literal Type
"credit"
dan:
"debit"
Sekarang memastikan type expense hanya dua kemungkinan.
Type Assertion
Kita belajar:
element as HTMLInputElement
Sekarang digunakan ketika mengambil element dari DOM.
Class
Kita belajar:
class ShoppingCart<T> {
...
}
Sekarang konsep class dipakai untuk:
class ExpenseTracker {
...
}
Generic
Kita belajar:
class ShoppingCart<T>
dan:
function swap<T>(...)
Konsep ini bisa digunakan ketika project membutuhkan struktur reusable yang type-safe.
Type Guard
Kita belajar:
typeof value === "string"
Sekarang kita mungkin akan menggunakan conditional checking berdasarkan:
expense.type
DOM
Sekarang konsep ini benar-benar digunakan:
document.querySelector(...)
Event Listener
Sekarang:
button.addEventListener("click", ...)
digunakan untuk membuat aplikasi interaktif.
23. Gambaran Arsitektur Aplikasi
Kalau disederhanakan, aplikasi ini kira-kira mempunyai struktur seperti ini:
USER
β
βΌ
HTML FORM
β
βββββββββββββ΄ββββββββββββ
β β
Type Description
β β
βββββββββββββ¬ββββββββββββ
β
Amount
β
βΌ
Add Expense
β
βΌ
Event Listener
β
βΌ
Expense Object
β
βΌ
ExpenseTracker
β
ββββββββββββββΌβββββββββββββ
βΌ βΌ βΌ
Add Delete Calculate
Expense Expense Total
β β β
ββββββββββββββΌβββββββββββββ
βΌ
Update
DOM
β
ββββββββββββ΄βββββββββββ
βΌ βΌ
Expense List Total Balance
Ini belum tentu persis struktur kode akhirnya, tetapi sangat bagus untuk memahami alur aplikasinya.
24. Yang Sebenarnya Sedang Diajarkan Instructor
Kalau kita lihat lebih dalam, tujuan lecture ini bukan sekadar:
“Mari kita membuat aplikasi expense tracker.”
Tetapi:
“Mari kita belajar kapan dan mengapa konsep TypeScript digunakan dalam aplikasi nyata.”
Ini perbedaan besar.
Sebelumnya:
Apa itu Generic?
Apa itu Union?
Apa itu Type Assertion?
Apa itu Class?
Apa itu Type Guard?
Sekarang berubah menjadi:
Saya punya masalah nyata.
β
Konsep TypeScript mana yang cocok?
β
Bagaimana menerapkannya?
β
Apa keuntungan type safety-nya?
Itulah alasan instructor mengatakan project ini akan:
enhance our knowledge
Karena kita tidak lagi hanya menghafal syntax.
25. Contoh Cara Berpikir Developer
Misalnya kita menemukan requirement:
Expense hanya boleh memiliki tipe credit atau debit.
Kita berpikir:
Problem:
Bagaimana mencegah value lain?
Solusi TypeScript:
type ExpenseType = "credit" | "debit";
Problem lain:
Kita mengambil input dari DOM dan ingin menggunakan
.value.
Kita berpikir:
Problem:
TypeScript hanya mengetahui Element.
Solusi:
as HTMLInputElement
Problem:
User klik tombol Add Expense.
Kita berpikir:
Problem:
Bagaimana menjalankan function ketika tombol diklik?
Solusi:
addEventListener("click", ...)
Problem:
Kita perlu mengorganisasi seluruh logic expense.
Kita berpikir:
Problem:
Banyak data + banyak behavior.
Solusi:
class ExpenseTracker
26. Jadi Jangan Langsung Coding
Ini juga pelajaran penting dari lecture.
Sebelum coding, kita harus memahami:
Data apa yang kita punya?
Expense
Property apa yang diperlukan?
type
description
amount
date
Operasi apa yang diperlukan?
add
delete
calculate total
show expense
show details
Apa yang berinteraksi dengan user?
form
button
expense list
Event apa yang diperlukan?
click
Bagaimana data memengaruhi UI?
credit β tambah balance
debit β kurangi balance
Dengan cara berpikir seperti ini, coding menjadi jauh lebih mudah.
27. Ringkasan Flow Ketika Add Expense
Misalnya user memasukkan:
Type: Debit
Description: Groceries
Amount: 230
Kemudian klik:
Add Expense
Maka:
1. Click event terjadi
β
2. TypeScript menangkap event
β
3. Ambil value dari input
β
4. Buat Expense object
β
5. Masukkan ke expenses array
β
6. Cek type
β
7. Karena debit β total berkurang
β
8. Generate HTML
β
9. Insert HTML ke DOM
β
10. Update total di header
28. Ringkasan Flow Ketika Delete
Misalnya:
Total = $9,770
Groceries = Debit $230
User menghapus Groceries.
Delete
β
Cari expense
β
Cek type
β
Debit
β
Total + $230
β
$10,000
β
Hapus dari list
β
Update DOM
Kalau credit:
Credit $5500
β
Delete
β
Total - $5500
29. Ringkasan Flow Ketika Melihat Detail
User klik:
YouTube Earnings
Kemudian:
Click
β
Cari expense yang dipilih
β
Ambil data expense
β
Description
Amount
Date
Type
β
Tampilkan detail
30. Cheat Sheet Lecture Ini
A. Expense Type
type ExpenseType = "credit" | "debit";
Artinya:
Hanya boleh credit atau debit.
B. Credit
Uang masuk
+
Tambah total
Contoh:
YouTube Earnings +$5,500
C. Debit
Uang keluar
-
Kurangi total
Contoh:
Groceries -$230
D. Type Assertion
const input =
element as HTMLInputElement;
Artinya:
Anggap element ini sebagai HTMLInputElement.
E. Class
class ExpenseTracker {
...
}
Artinya:
Menggabungkan data dan behavior aplikasi dalam satu struktur.
F. DOM
document.querySelector(...)
Artinya:
Mengambil element HTML dari halaman.
G. Event Listener
button.addEventListener("click", () => {
...
});
Artinya:
Jalankan kode ketika button diklik.
H. Dynamic Content
Data
β
TypeScript
β
HTML dibuat
β
DOM diperbarui
31. Hal Terpenting yang Harus Kamu Tangkap
Kalau harus diringkas menjadi satu kalimat:
Lecture ini adalah pengenalan project yang akan digunakan untuk mempraktikkan berbagai konsep TypeScript yang sudah dipelajari sebelumnya.
Dan project-nya adalah:
EXPENSE TRACKER
dengan fitur:
Expense Tracker
β
ββββββββββββββββΌβββββββββββββββ
βΌ βΌ βΌ
CREDIT DEBIT TOTAL
β β β
+ amount - amount balance
β β
ββββββββ¬ββββββββ
βΌ
Expense List
β
ββββββββ΄βββββββ
βΌ βΌ
Delete Details
Yang paling penting, mulai dari lecture ini kita tidak lagi hanya bertanya:
“Apa itu Union Type?”
tetapi mulai bertanya:
“Saya punya masalah di project. Konsep TypeScript apa yang paling tepat untuk menyelesaikan masalah tersebut?”
Itulah inti perpindahan dari belajar teori TypeScript β menjadi mampu menggunakan TypeScript dalam project nyata.