DP
Kembali ke Tutorial
TypeScriptPemula

TypeScript untuk Pemula: Panduan Lengkap

Pelajari TypeScript dari dasar dengan contoh praktis: tipe primitif, object, union, interface, generics, narrowing, utility types, dan pola aman untuk data API.

8 menit baca25 Mei 2026oleh Reza Maulana

TypeScript untuk Pemula: Panduan Lengkap

TypeScript adalah JavaScript yang diberi sistem tipe statis. Kode TypeScript tetap dikompilasi menjadi JavaScript, tetapi sebelum dijalankan kita mendapatkan bantuan pemeriksaan tipe. Bantuan ini sangat berguna ketika aplikasi mulai memiliki banyak file, banyak data, dan banyak orang yang ikut mengubah kode.

Tujuan TypeScript bukan membuat kode menjadi lebih rumit. Tujuannya adalah membuat kontrak antarbagian aplikasi lebih jelas: function menerima apa, object memiliki field apa, API mengembalikan bentuk data seperti apa, dan kesalahan apa yang dapat dicegah sebelum kode sampai ke browser atau server.

Tujuan Belajar

Setelah membaca tutorial ini, kamu diharapkan mampu:

  • Menulis tipe dasar untuk variable, parameter, dan return value.
  • Membuat tipe object dengan type dan interface.
  • Menggunakan union type untuk nilai yang memiliki beberapa kemungkinan bentuk.
  • Melakukan narrowing agar TypeScript memahami cabang logika.
  • Menggunakan generics untuk function dan struktur data yang fleksibel.
  • Menerapkan utility types seperti Pick, Omit, Partial, dan Readonly.
  • Mendesain tipe sederhana untuk data API.

Mengapa TypeScript Berguna?

JavaScript sangat fleksibel. Fleksibilitas itu menyenangkan saat belajar, tetapi dapat menjadi sumber bug ketika aplikasi membesar. Contoh sederhana:

javascript
function formatPrice(price) {
  return price.toLocaleString("id-ID");
}

formatPrice(15000);
formatPrice("15000");
formatPrice(null);

Kode ini mungkin terlihat aman, tetapi null akan membuat error saat runtime. Dengan TypeScript, kita bisa menyatakan bahwa price harus berupa number.

typescript
function formatPrice(price: number): string {
  return price.toLocaleString("id-ID");
}

formatPrice(15000);
// formatPrice(null); // Error sebelum aplikasi dijalankan

Kesalahan yang lebih cepat ditemukan biasanya lebih murah diperbaiki.

Tipe Primitif

Tipe primitif yang sering dipakai adalah string, number, boolean, null, dan undefined.

typescript
const title: string = "Belajar TypeScript";
const durationMinutes: number = 90;
const isPublished: boolean = true;

Pada banyak kasus, TypeScript bisa melakukan inference, yaitu menebak tipe dari nilai awal.

typescript
const title = "Belajar TypeScript"; // string
const durationMinutes = 90; // number
const isPublished = true; // boolean

Gunakan anotasi tipe saat tipe tidak jelas dari nilai awal, terutama parameter function dan data kosong.

typescript
const tags: string[] = [];

function addTag(tag: string) {
  tags.push(tag);
}

Array dan Tuple

Array dipakai untuk daftar dengan tipe elemen yang sama.

typescript
const scores: number[] = [80, 90, 75];
const names: Array<string> = ["Ayu", "Bima", "Citra"];

Tuple dipakai saat posisi elemen punya makna khusus.

typescript
const coordinate: [number, number] = [-6.889, 109.675];
const httpResult: [number, string] = [200, "OK"];

Tuple sebaiknya digunakan secukupnya. Jika jumlah field bertambah atau butuh nama yang jelas, object biasanya lebih mudah dibaca.

Object, Type Alias, dan Interface

Untuk object, kita bisa memakai type atau interface.

typescript
type User = {
  id: string;
  name: string;
  email: string;
  role: "admin" | "user";
};

function getDisplayName(user: User): string {
  return `${user.name} <${user.email}>`;
}

interface juga umum dipakai untuk struktur object.

typescript
interface Course {
  id: string;
  title: string;
  lessonCount: number;
  published: boolean;
}

const course: Course = {
  id: "course-1",
  title: "Dasar TypeScript",
  lessonCount: 12,
  published: true,
};

Keduanya valid. Untuk pemula, pilih salah satu dan konsisten di satu project. Banyak tim memakai type untuk union/komposisi dan interface untuk object yang dapat diperluas.

Optional Property dan Nullable

Optional property ditandai dengan ?. Artinya field boleh tidak ada.

typescript
type Profile = {
  id: string;
  name: string;
  avatarUrl?: string;
};

Nullable berarti field ada, tetapi nilainya boleh null.

typescript
type Article = {
  id: string;
  title: string;
  publishedAt: Date | null;
};

Perbedaan ini penting saat bekerja dengan API dan database. undefined sering berarti belum disediakan, sedangkan null sering berarti sengaja kosong.

Union Type

Union type menyatakan nilai dapat berupa salah satu dari beberapa tipe.

typescript
type Status = "draft" | "published" | "archived";

function getStatusLabel(status: Status): string {
  if (status === "draft") return "Draft";
  if (status === "published") return "Terbit";
  return "Arsip";
}

Union lebih aman daripada string bebas karena TypeScript dapat menolak nilai yang tidak termasuk daftar.

typescript
// const status: Status = "deleted"; // Error
const status: Status = "published";

Narrowing dengan typeof dan in

Ketika sebuah nilai memiliki beberapa kemungkinan tipe, TypeScript perlu bukti sebelum kita memakai method tertentu.

typescript
function normalizeId(id: string | number): string {
  if (typeof id === "number") {
    return id.toString();
  }

  return id.trim();
}

Untuk object union, operator in dapat membantu.

typescript
type SuccessResponse = { ok: true; data: string[] };
type ErrorResponse = { ok: false; message: string };

type ApiResponse = SuccessResponse | ErrorResponse;

function renderResponse(response: ApiResponse): string {
  if (response.ok) {
    return `Total data: ${response.data.length}`;
  }

  return `Error: ${response.message}`;
}

Property ok menjadi pembeda bentuk data. Pola ini disebut discriminated union dan sangat berguna untuk state UI.

State UI dengan Discriminated Union

Daripada membuat banyak boolean seperti isLoading, isError, dan isSuccess, kita bisa memakai union.

typescript
type LoadState<T> =
  | { status: "idle" }
  | { status: "loading" }
  | { status: "success"; data: T }
  | { status: "error"; message: string };

function getMessage(state: LoadState<string[]>): string {
  switch (state.status) {
    case "idle":
      return "Belum memuat data";
    case "loading":
      return "Memuat data";
    case "success":
      return `Ada ${state.data.length} data`;
    case "error":
      return state.message;
  }
}

Keuntungannya, data hanya tersedia pada status yang tepat. Ini mengurangi risiko membaca data saat request masih loading.

Generics

Generics dipakai saat function atau tipe perlu bekerja untuk banyak tipe tanpa kehilangan informasi tipe.

typescript
function firstItem<T>(items: T[]): T | undefined {
  return items[0];
}

const firstNumber = firstItem([10, 20, 30]);
const firstName = firstItem(["Ayu", "Bima"]);

T adalah placeholder tipe. TypeScript akan mengisinya berdasarkan argumen yang diberikan.

Contoh yang lebih dekat dengan API:

typescript
type PaginatedResult<T> = {
  items: T[];
  page: number;
  totalPages: number;
};

type Tutorial = {
  id: string;
  title: string;
};

const result: PaginatedResult<Tutorial> = {
  items: [{ id: "t1", title: "TypeScript" }],
  page: 1,
  totalPages: 3,
};

Dengan generics, struktur pagination bisa dipakai ulang untuk tutorial, course, comment, atau data lain.

Utility Types

TypeScript menyediakan utility types untuk membuat tipe turunan.

typescript
type User = {
  id: string;
  name: string;
  email: string;
  passwordHash: string;
};

type PublicUser = Omit<User, "passwordHash">;
type UserPreview = Pick<User, "id" | "name">;
type UpdateUserInput = Partial<Pick<User, "name" | "email">>;
type ImmutableUser = Readonly<User>;

Gunakan utility types untuk menghindari duplikasi tipe. Namun jangan terlalu memaksa. Jika tipe turunan menjadi sulit dibaca, tipe eksplisit kadang lebih baik.

Mendesain Tipe untuk API

Misalkan API mengembalikan daftar tutorial.

json
{
  "items": [
    { "id": "t1", "title": "React Hooks", "published": true }
  ],
  "page": 1,
  "totalPages": 5
}

Tipe TypeScript-nya bisa ditulis seperti ini.

typescript
type TutorialListItem = {
  id: string;
  title: string;
  published: boolean;
};

type ListResponse<T> = {
  items: T[];
  page: number;
  totalPages: number;
};

type TutorialListResponse = ListResponse<TutorialListItem>;

Saat data berasal dari luar aplikasi, TypeScript hanya membantu saat compile time. Untuk validasi runtime, gunakan pemeriksaan manual atau library schema validation. Jangan menganggap semua JSON dari API pasti sesuai tipe hanya karena sudah diberi anotasi.

Kesalahan Umum

KesalahanMengapa bermasalahAlternatif
Terlalu sering memakai anyTypeScript kehilangan manfaat utamanyaGunakan unknown, tipe eksplisit, atau generics.
Menulis tipe terlalu besarKode sulit dirawatPecah menjadi tipe kecil yang punya tujuan jelas.
Menganggap tipe sama dengan validasi runtimeData eksternal tetap bisa salahValidasi JSON sebelum dipakai.
Membuat union string tanpa narrowingCabang logika rawan salahGunakan discriminated union.

Coba Sendiri

Buat tipe untuk fitur daftar course dengan ketentuan:

  • CourseLevel hanya boleh "pemula", "menengah", atau "lanjutan".
  • CourseCard memiliki id, title, level, lessonCount, dan publishedAt.
  • Response API berbentuk generic ListResponse<T>.
  • State UI memakai LoadState<T> dengan status idle, loading, success, dan error.

Setelah tipe selesai, buat function renderCourseCount yang menerima LoadState<CourseCard[]> dan mengembalikan pesan sesuai status.

typescript
type CourseLevel = "pemula" | "menengah" | "lanjutan";

type CourseCard = {
  id: string;
  title: string;
  level: CourseLevel;
  lessonCount: number;
  publishedAt: string;
};

type LoadState<T> =
  | { status: "idle" }
  | { status: "loading" }
  | { status: "success"; data: T }
  | { status: "error"; message: string };

function renderCourseCount(state: LoadState<CourseCard[]>): string {
  if (state.status === "success") {
    return `${state.data.length} course tersedia`;
  }

  if (state.status === "error") return state.message;
  if (state.status === "loading") return "Memuat course";
  return "Belum ada request";
}

Cek Pemahaman

Kuis

Manakah pernyataan paling tepat tentang TypeScript?

Pilih satu jawaban.

Kuis

Mengapa discriminated union cocok untuk state loading data?

Pilih satu jawaban.

Ringkasan

TypeScript membantu kita menulis kontrak data yang jelas. Mulailah dari tipe primitif, object, union, dan narrowing. Setelah itu, gunakan generics dan utility types untuk membuat tipe yang fleksibel tetapi tetap mudah dibaca. Saat bekerja dengan data dari luar aplikasi, ingat bahwa TypeScript bukan validasi runtime; tetap lakukan validasi sebelum data dipercaya.

#typescript#javascript#frontend#backend#type-safety
Apakah konten ini membantu?

Feedback kamu membantu kami memperbaiki materi berikutnya.

Diskusi (0)

Silakan masuk terlebih dahulu untuk ikut berdiskusi

Login Sekarang