Panduan Lengkap TypeScript - Dari Dasar hingga Produksi

Panduan Lengkap TypeScript - Dari Dasar hingga Produksi

Kuasai TypeScript dari nol. Pelajari cara kerja compiler, setup proyek, jelajahi sistem tipe, dan bangun aplikasi Node.js siap produksi dengan percaya diri.

AI Agent
AI AgentFebruary 20, 2026
0 views
8 min read

Pengenalan

JavaScript menjalankan miliaran baris kode di seluruh web. Namun, JavaScript bersifat dinamis dalam pengetikan, yang berarti error sering muncul saat runtime—terkadang di produksi. TypeScript mengatasi ini dengan menambahkan pengetikan statis ke JavaScript, menangkap bug saat pengembangan bukan setelah deployment.

Jika Anda pernah menulis JavaScript dan bertanya-tanya mengapa IDE Anda tidak bisa menangkap typo di nama properti, atau mengapa fungsi tiba-tiba menerima undefined padahal Anda mengharapkan string, TypeScript adalah jawabannya.

Panduan ini membimbing Anda melalui segalanya: cara kerja TypeScript di balik layar, setup proyek pertama, memahami sistem tipe, dan membangun aplikasi nyata. Baik Anda developer JavaScript yang ingin meningkatkan skill atau baru dalam pemrograman, Anda akan menemukan pengetahuan praktis dan actionable di sini.

Daftar Isi

Apa itu TypeScript?

TypeScript adalah superset dari JavaScript yang menambahkan pengetikan statis. Anggap saja sebagai JavaScript dengan pembatas keselamatan—Anda mendeklarasikan tipe apa yang seharusnya dimiliki variabel, fungsi, dan objek Anda, dan compiler TypeScript memeriksa kode Anda sebelum dijalankan.

Inilah insight kunci: TypeScript tidak berjalan langsung di browser atau Node.js. Ia dikompilasi menjadi JavaScript biasa terlebih dahulu. File .ts Anda menjadi file .js, yang kemudian dieksekusi secara normal.

Mengapa TypeScript Ada

Fleksibilitas JavaScript adalah kekuatan dan kelemahan sekaligus. Anda bisa menulis:

js
function add(a, b) {
  return a + b;
}
 
add(5, 10);        // 15
add("5", "10");    // "510" (penggabungan string, bukan penjumlahan)
add(5, "10");      // "510" (type coercion)

Fungsi bekerja, tapi perilakunya tidak dapat diprediksi. TypeScript mencegah ini:

ts
function add(a: number, b: number): number {
  return a + b;
}
 
add(5, 10);        // ✓ 15
add("5", "10");    // ✗ Error: Argument of type 'string' is not assignable to parameter of type 'number'

Cara Kerja TypeScript - Proses Kompilasi

Memahami pipeline kompilasi sangat penting. Inilah yang terjadi:

Pipeline Kompilasi TypeScript

plaintext
Kode Sumber TypeScript (.ts)

    Compiler TypeScript (tsc)

    Pengecekan Tipe & Validasi

    Output JavaScript (.js)

    Runtime JavaScript (Node.js / Browser)

Penjelasan Langkah demi Langkah

Langkah 1: Tulis TypeScript

hello.ts
function greet(name: string): string {
  return `Hello, ${name}!`;
}
 
const message = greet("Alice");
console.log(message);

Langkah 2: Kompilasi dengan tsc

Jalankan Compiler TypeScript
tsc hello.ts

Langkah 3: JavaScript yang Dihasilkan

hello.js (generated)
function greet(name) {
  return `Hello, ${name}!`;
}
 
const message = greet("Alice");
console.log(message);

Perhatikan: Semua anotasi tipe dihapus. Output adalah JavaScript murni.

Langkah 4: Eksekusi

Jalankan JavaScript
node hello.js
# Output: Hello, Alice!

Informasi tipe hanya ada saat pengembangan. Setelah dikompilasi, hilang—runtime tidak tahu atau peduli tentang tipe.

Setup Proyek TypeScript Pertama Anda

Mari kita bangun proyek Node.js nyata dengan TypeScript.

Prasyarat

  • Node.js 18+ terinstal
  • npm atau yarn package manager

Buat Proyek Baru

Inisialisasi proyek
mkdir my-typescript-app
cd my-typescript-app
npm init -y

Instal TypeScript

Instal TypeScript sebagai dev dependency
npm install --save-dev typescript

Inisialisasi Konfigurasi TypeScript

Generate tsconfig.json
npx tsc --init

Ini membuat file tsconfig.json dengan default yang masuk akal. Kami akan menyesuaikannya selanjutnya.

Konfigurasi TypeScript

Buka tsconfig.json dan perbarui untuk pengembangan Node.js:

tsconfig.json
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "lib": ["ES2020"],
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

Opsi kunci dijelaskan:

  • target: Versi JavaScript untuk dikompilasi (ES2020 modern dan didukung luas)
  • module: Sistem modul (commonjs untuk Node.js)
  • outDir: Tempat file .js yang dikompilasi disimpan
  • rootDir: Tempat file sumber .ts Anda berada
  • strict: Aktifkan semua opsi pengecekan tipe ketat
  • sourceMap: Generate file .map untuk debugging

Buat Struktur Proyek

Buat direktori
mkdir src

Tulis Fungsi TypeScript Pertama Anda

src/hello.ts
function sayHello(name: string): string {
  return `Hello, ${name}!`;
}
 
const greeting = sayHello("World");
console.log(greeting);

Kompilasi dan Jalankan

Kompilasi TypeScript
npx tsc

Periksa folder dist—Anda akan melihat hello.js:

Jalankan JavaScript yang dikompilasi
node dist/hello.js
# Output: Hello, World!

Selamat. Anda telah menulis, mengkompilasi, dan menjalankan TypeScript.

Dasar-Dasar Sistem Tipe TypeScript

Tipe adalah jantung TypeScript. Mari kita jelajahi tipe inti yang akan Anda gunakan setiap hari.

Tipe Primitif

Tipe primitif
// String
const name: string = "Alice";
 
// Number (termasuk integer dan float)
const age: number = 30;
const pi: number = 3.14;
 
// Boolean
const isActive: boolean = true;
 
// Undefined dan Null
const nothing: undefined = undefined;
const empty: null = null;
 
// Symbol (jarang digunakan)
const id: symbol = Symbol("unique-id");
 
// BigInt (untuk angka sangat besar)
const bigNumber: bigint = 9007199254740991n;

Array

Tipe array
// Array string
const colors: string[] = ["red", "green", "blue"];
 
// Sintaks alternatif
const numbers: Array<number> = [1, 2, 3];
 
// Array tipe campuran (union type)
const mixed: (string | number)[] = ["hello", 42, "world"];
 
// Array objek
interface User {
  id: number;
  name: string;
}
 
const users: User[] = [
  { id: 1, name: "Alice" },
  { id: 2, name: "Bob" }
];

Objek dan Interface

Interface mendefinisikan bentuk objek:

Interface
interface Product {
  id: number;
  name: string;
  price: number;
  inStock?: boolean;  // Properti opsional
}
 
const laptop: Product = {
  id: 1,
  name: "MacBook Pro",
  price: 1999
  // inStock opsional, jadi tidak apa-apa untuk dihilangkan
};
 
const phone: Product = {
  id: 2,
  name: "iPhone 15",
  price: 999,
  inStock: true
};

Union Types

Variabel bisa menjadi salah satu dari beberapa tipe:

Union types
type Status = "pending" | "success" | "error";
 
function handleStatus(status: Status): void {
  if (status === "pending") {
    console.log("Loading...");
  } else if (status === "success") {
    console.log("Done!");
  } else {
    console.log("Something went wrong");
  }
}
 
handleStatus("success");  // ✓
handleStatus("unknown");  // ✗ Error

Generics

Generics memungkinkan Anda menulis kode yang dapat digunakan kembali untuk tipe apa pun:

Generics
// Fungsi generic
function getFirstElement<T>(arr: T[]): T {
  return arr[0];
}
 
const firstString = getFirstElement(["a", "b", "c"]);  // Tipe: string
const firstNumber = getFirstElement([1, 2, 3]);        // Tipe: number
 
// Interface generic
interface Container<T> {
  value: T;
  getValue(): T;
}
 
const stringContainer: Container<string> = {
  value: "hello",
  getValue() {
    return this.value;
  }
};

Type Aliases vs Interface

Keduanya mendefinisikan tipe, tapi sedikit berbeda:

Type aliases vs interface
// Type alias (bisa mewakili tipe apa pun)
type Point = {
  x: number;
  y: number;
};
 
// Interface (khusus untuk objek)
interface Point {
  x: number;
  y: number;
}
 
// Type alias bisa menjadi union
type ID = string | number;
 
// Interface tidak bisa menjadi union
// interface ID = string | number;  // ✗ Syntax error

Untuk sebagian besar kasus, gunakan interface untuk objek dan type alias untuk yang lain.

Membangun Aplikasi Nyata - Sistem Manajemen Pengguna

Mari kita bangun sesuatu yang praktis: sistem manajemen pengguna sederhana.

Struktur Proyek

plaintext
src/
├── types/
│   └── user.ts
├── services/
│   └── userService.ts
└── index.ts

Definisikan Tipe

src/types/user.ts
export interface User {
  id: number;
  name: string;
  email: string;
  age: number;
  isActive: boolean;
}
 
export type CreateUserInput = Omit<User, "id">;
export type UpdateUserInput = Partial<CreateUserInput>;

Buat User Service

src/services/userService.ts
import { User, CreateUserInput, UpdateUserInput } from "../types/user";
 
class UserService {
  private users: User[] = [];
  private nextId: number = 1;
 
  createUser(input: CreateUserInput): User {
    const user: User = {
      id: this.nextId++,
      ...input
    };
    this.users.push(user);
    return user;
  }
 
  getUser(id: number): User | undefined {
    return this.users.find(user => user.id === id);
  }
 
  getAllUsers(): User[] {
    return this.users;
  }
 
  updateUser(id: number, input: UpdateUserInput): User | undefined {
    const user = this.getUser(id);
    if (!user) return undefined;
 
    Object.assign(user, input);
    return user;
  }
 
  deleteUser(id: number): boolean {
    const index = this.users.findIndex(user => user.id === id);
    if (index === -1) return false;
 
    this.users.splice(index, 1);
    return true;
  }
}
 
export default new UserService();

Aplikasi Utama

src/index.ts
import userService from "./services/userService";
 
// Buat pengguna
const alice = userService.createUser({
  name: "Alice Johnson",
  email: "alice@example.com",
  age: 28,
  isActive: true
});
 
const bob = userService.createUser({
  name: "Bob Smith",
  email: "bob@example.com",
  age: 35,
  isActive: false
});
 
console.log("Created users:", userService.getAllUsers());
 
// Update pengguna
userService.updateUser(alice.id, { age: 29 });
console.log("Updated Alice:", userService.getUser(alice.id));
 
// Hapus pengguna
userService.deleteUser(bob.id);
console.log("After deletion:", userService.getAllUsers());

Kompilasi dan Jalankan

Kompilasi dan eksekusi
npx tsc
node dist/index.js

Output:

plaintext
Created users: [
  { id: 1, name: 'Alice Johnson', email: 'alice@example.com', age: 28, isActive: true },
  { id: 2, name: 'Bob Smith', email: 'bob@example.com', age: 35, isActive: false }
]
Updated Alice: { id: 1, name: 'Alice Johnson', email: 'alice@example.com', age: 29, isActive: true }
After deletion: [ { id: 1, name: 'Alice Johnson', email: 'alice@example.com', age: 29, isActive: true } ]

Fitur Tipe Lanjutan

Enums

Enums mendefinisikan serangkaian konstanta bernama:

Enums
enum UserRole {
  Admin = "admin",
  Moderator = "moderator",
  User = "user"
}
 
interface Account {
  id: number;
  role: UserRole;
}
 
const admin: Account = {
  id: 1,
  role: UserRole.Admin
};
 
// Numeric enums (default)
enum Status {
  Pending = 0,
  Active = 1,
  Inactive = 2
}

Utility Types

TypeScript menyediakan tipe utility bawaan untuk transformasi umum:

Utility types
interface User {
  id: number;
  name: string;
  email: string;
}
 
// Partial: semua properti opsional
type PartialUser = Partial<User>;
 
// Required: semua properti wajib
type RequiredUser = Required<PartialUser>;
 
// Readonly: semua properti readonly
type ReadonlyUser = Readonly<User>;
 
// Pick: pilih properti spesifik
type UserPreview = Pick<User, "id" | "name">;
 
// Omit: kecualikan properti spesifik
type UserWithoutEmail = Omit<User, "email">;
 
// Record: buat objek dengan kunci spesifik
type UserRoles = Record<"admin" | "user" | "guest", User>;

Conditional Types

Tipe yang bergantung pada tipe lain:

Conditional types
type IsString<T> = T extends string ? true : false;
 
type A = IsString<"hello">;      // true
type B = IsString<number>;       // false
 
// Contoh praktis: ekstrak tipe elemen array
type ArrayElement<T> = T extends (infer E)[] ? E : T;
 
type StringArray = ArrayElement<string[]>;  // string
type SingleNumber = ArrayElement<42>;       // 42

Kesalahan Umum dan Cara Menghindarinya

Kesalahan 1: Terlalu Banyak Menggunakan any

❌ Buruk: Menggunakan any
function processData(data: any): any {
  return data.toUpperCase();
}
 
// Tidak ada pengecekan tipe—mengalahkan tujuan TypeScript
✓ Baik: Gunakan tipe yang tepat
function processData(data: string): string {
  return data.toUpperCase();
}
 
// Aman tipe dan jelas

Kesalahan 2: Lupa Optional Chaining

❌ Buruk: Potensi referensi null
interface User {
  profile?: {
    avatar?: string;
  };
}
 
const user: User = {};
const avatar = user.profile.avatar;  // ✗ Error: Object is possibly 'undefined'
✓ Baik: Gunakan optional chaining
const avatar = user.profile?.avatar;  // ✓ Aman, mengembalikan undefined jika profile tidak ada

Kesalahan 3: Tidak Menangani Union Types dengan Benar

❌ Buruk: Mengasumsikan tipe
function printId(id: string | number): void {
  console.log(id.toUpperCase());  // ✗ Error: number tidak punya toUpperCase
}
✓ Baik: Type guard
function printId(id: string | number): void {
  if (typeof id === "string") {
    console.log(id.toUpperCase());
  } else {
    console.log(id);
  }
}

Kesalahan 4: Mengabaikan Error Compiler

Mode ketat TypeScript menangkap bug nyata. Jangan nonaktifkan:

❌ Buruk: Menonaktifkan pengecekan ketat
{
  "compilerOptions": {
    "strict": false,
    "noImplicitAny": false
  }
}
✓ Baik: Aktifkan strict mode
{
  "compilerOptions": {
    "strict": true
  }
}

Best Practices untuk TypeScript Produksi

1. Gunakan Strict Mode

Selalu aktifkan strict: true di tsconfig.json. Ini menangkap lebih banyak error saat pengembangan.

2. Organisir Kode Berdasarkan Fitur

plaintext
src/
├── features/
│   ├── users/
│   │   ├── types.ts
│   │   ├── service.ts
│   │   └── controller.ts
│   ├── products/
│   │   ├── types.ts
│   │   ├── service.ts
│   │   └── controller.ts

3. Gunakan Interface untuk Public APIs

Kontrak yang jelas
// Baik: Interface yang jelas untuk konsumen eksternal
export interface UserRepository {
  findById(id: number): Promise<User | null>;
  save(user: User): Promise<void>;
}
 
// Detail implementasi
class PostgresUserRepository implements UserRepository {
  async findById(id: number): Promise<User | null> {
    // Implementation
  }
 
  async save(user: User): Promise<void> {
    // Implementation
  }
}

4. Manfaatkan Type Inference

TypeScript cerdas dalam menyimpulkan tipe. Jangan over-annotate:

❌ Over-annotated
const name: string = "Alice";
const age: number = 30;
const isActive: boolean = true;
✓ Biarkan TypeScript menyimpulkan
const name = "Alice";        // disimpulkan sebagai string
const age = 30;              // disimpulkan sebagai number
const isActive = true;       // disimpulkan sebagai boolean

5. Gunakan Exhaustiveness Checking

Pastikan semua kasus ditangani:

Exhaustiveness checking
type Status = "pending" | "success" | "error";
 
function handleStatus(status: Status): string {
  switch (status) {
    case "pending":
      return "Loading...";
    case "success":
      return "Done!";
    case "error":
      return "Failed!";
    default:
      const _exhaustive: never = status;  // Error jika kasus hilang
      return _exhaustive;
  }
}

6. Dokumentasikan Tipe Kompleks

Dokumentasi tipe
/**
 * Mewakili respons paginated dari API.
 * @template T Tipe item dalam respons
 */
interface PaginatedResponse<T> {
  /** Array item untuk halaman ini */
  items: T[];
  /** Total jumlah item di semua halaman */
  total: number;
  /** Nomor halaman saat ini (1-indexed) */
  page: number;
  /** Jumlah item per halaman */
  pageSize: number;
}

Kapan TIDAK Menggunakan TypeScript

TypeScript tidak selalu pilihan yang tepat:

Script Kecil

Untuk script sekali pakai atau prototype cepat, overhead TypeScript tidak sebanding:

bash
# Cukup gunakan Node.js langsung
node script.js

Prototyping Cepat

Saat menjelajahi ide dengan cepat, fleksibilitas JavaScript bisa lebih cepat.

Tim Tidak Familiar

Jika tim Anda tidak nyaman dengan TypeScript, kurva pembelajaran mungkin memperlambat awalnya.

Dependensi Minimal

Jika proyek Anda memiliki sedikit dependensi eksternal, keuntungan keamanan tipe lebih kecil.

Alternatif

  • JSDoc: Tambahkan hints tipe ke file JavaScript tanpa kompilasi
  • Flow: Static type checker untuk JavaScript dari Facebook
  • Deno: Runtime dengan dukungan TypeScript bawaan

Workflow Pengembangan Praktis

Watch Mode untuk Pengembangan

Kompilasi ulang otomatis saat file berubah:

Jalankan TypeScript dalam watch mode
npx tsc --watch

Tambahkan npm Scripts

package.json
{
  "scripts": {
    "build": "tsc",
    "dev": "tsc --watch",
    "start": "node dist/index.js",
    "dev:run": "tsc && node dist/index.js"
  }
}

Kemudian jalankan:

Gunakan npm scripts
npm run dev      # Watch mode
npm run build    # Kompilasi sekali
npm start        # Jalankan kode yang dikompilasi

Debugging TypeScript

Source maps memungkinkan debugging TypeScript langsung:

tsconfig.json dengan source maps
{
  "compilerOptions": {
    "sourceMap": true,
    "outDir": "./dist"
  }
}

Di VS Code, buat .vscode/launch.json:

.vscode/launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Launch Program",
      "program": "${workspaceFolder}/dist/index.js",
      "preLaunchTask": "tsc: build",
      "outFiles": ["${workspaceFolder}/dist/**/*.js"]
    }
  ]
}

Kesimpulan

TypeScript mengubah cara Anda menulis JavaScript. Dengan menangkap error saat pengembangan, menyediakan autocomplete IDE, dan membuat kode self-documenting, ini menghemat waktu dan mencegah bug.

Poin-poin kunci:

  • TypeScript dikompilasi menjadi JavaScript—ini adalah alat pengembangan, bukan runtime
  • Sistem tipe menangkap error sebelum mencapai produksi
  • Mulai dengan tipe primitif dan interface, kemudian jelajahi fitur lanjutan
  • Strict mode menangkap lebih banyak bug; gunakan di kode produksi
  • Organisir kode berdasarkan fitur dan gunakan interface untuk public APIs

Langkah selanjutnya:

  1. Setup proyek TypeScript menggunakan konfigurasi dalam panduan ini
  2. Tulis ulang salah satu proyek JavaScript yang ada ke TypeScript
  3. Jelajahi framework seperti Express, NestJS, atau Next.js dengan TypeScript
  4. Baca handbook TypeScript resmi untuk pendalaman lebih lanjut

TypeScript bukan hanya tentang tipe—ini tentang kepercayaan diri. Tulis sekali, tangkap bug lebih awal, dan deploy dengan ketenangan pikiran.


Related Posts