Daftar Isi

Mengenal TypeScript: Optional Properties, Optional Chaining, & Enum

This article has been translated into English version: Learn TypeScript: Optional Properties, Optional Chaining, & Enum

TypeScript menawarkan sistem tipe data yang kuat untuk membantu pengembangan aplikasi yang lebih aman dan mudah dipelihara. Artikel ini akan membahas dua fitur penting dalam sistem tipe TypeScript: Optional Properties, Optional Chaining, dan Enum.

Optional Properties

Dalam TypeScript, kita bisa menandai properti sebagai opsional dengan menambahkan tanda tanya (?) setelah nama properti. Ini berarti properti tersebut boleh ada atau tidak ada dalam sebuah objek.

/** Mendefinisikan tipe dengan optional properties */
type User = {
  id: number;
  name: string;
  /** email adalah optional property */
  email?: string;
  /** phone adalah optional property */
  phone?: string;
};

/** Membuat objek tanpa mengisi properti opsional */
const user1: User = {
  id: 1,
  name: "Budi",
};

/** Membuat objek dengan mengisi properti opsional */
const user2: User = {
  id: 2,
  name: "Ani",
  email: "ani@example.com",
  phone: "08123456789",
};

Beberapa manfaat dari optional properties antara lain:

Memungkinkan kita membuat struktur data yang fleksibel tanpa kehilangan keamanan tipe.

TypeScript akan memvalidasi bahwa properti wajib selalu ada.

Kode menjadi lebih ekspresif dan self-documenting.

Optional Chaining

Optional chaining adalah fitur yang memungkinkan kita mengakses properti atau memanggil metode dari objek yang mungkin null atau undefined tanpa menyebabkan error. Fitur ini direpresentasikan dengan operator ?..

type Address = {
  street: string;
  city: string;
  postalCode?: string;
};

type User = {
  id: number;
  name: string;
  address?: Address;
};

function getPostalCode(user: User): string | undefined {
  // Tanpa optional chaining
  // if (user.address && user.address.postalCode) {
  //   return user.address.postalCode;
  // }
  // return undefined;

  // Dengan optional chaining
  return user.address?.postalCode;
}

const user1: User = {
  id: 1,
  name: "Dian",
};

const user2: User = {
  id: 2,
  name: "Eko",
  address: {
    street: "Jl. Merdeka",
    city: "Jakarta",
  },
};

const user3: User = {
  id: 3,
  name: "Fira",
  address: {
    street: "Jl. Sudirman",
    city: "Jakarta",
    postalCode: "12345",
  },
};

console.log(getPostalCode(user1)); // undefined
console.log(getPostalCode(user2)); // undefined
console.log(getPostalCode(user3)); // "12345"

Optional chaining juga bisa digunakan untuk memanggil method yang mungkin tidak ada.

type Calculator = {
  add: (a: number, b: number) => number;
  subtract?: (a: number, b: number) => number;
};

const basicCalc: Calculator = {
  add: (a, b) => a + b,
};

const fullCalc: Calculator = {
  add: (a, b) => a + b,
  subtract: (a, b) => a - b,
};

// Memanggil method yang mungkin tidak ada
console.log(basicCalc.subtract?.(5, 3)); // undefined
console.log(fullCalc.subtract?.(5, 3)); // 2

Optional chaining sering digunakan bersama dengan nullish coalescing operator (??) untuk memberikan nilai default ketika hasilnya null atau undefined.

function getCity(user: User): string {
  return user.address?.city ?? "Kota tidak diketahui";
}

console.log(getCity(user1)); // "Kota tidak diketahui"
console.log(getCity(user2)); // "Jakarta"

Enum

Enum (enumeration) adalah cara untuk mendefinisikan sekelompok konstanta bernama. Enum memudahkan kita untuk mendokumentasikan maksud atau membuat kumpulan kasus yang berbeda.

/** Mendefinisikan enum */
enum Direction {
  Up,
  Down,
  Left,
  Right,
}

/** Menggunakan enum */
function move(direction: Direction): void {
  switch (direction) {
    case Direction.Up:
      console.log("Bergerak ke atas");
      break;
    case Direction.Down:
      console.log("Bergerak ke bawah");
      break;
    case Direction.Left:
      console.log("Bergerak ke kiri");
      break;
    case Direction.Right:
      console.log("Bergerak ke kanan");
      break;
  }
}

move(Direction.Up); // "Bergerak ke atas"
move(Direction.Right); // "Bergerak ke kanan"

Secara default, enum akan memberikan nilai numerik dimulai dari 0. Kita juga bisa memberikan nilai eksplisit untuk setiap anggota enum.

/** Enum dengan nilai string */
enum ApiStatus {
  Success = "SUCCESS",
  Error = "ERROR",
  Loading = "LOADING",
}

function handleApiResponse(status: ApiStatus): void {
  if (status === ApiStatus.Success) {
    console.log("API berhasil");
  } else if (status === ApiStatus.Error) {
    console.log("API gagal");
  } else {
    console.log("API sedang loading");
  }
}

handleApiResponse(ApiStatus.Success); // "API berhasil"

Untuk optimasi performa, TypeScript menyediakan const enum yang akan dihapus sepenuhnya saat kompilasi dan digantikan dengan nilai literalnya.

/** Const enum */
const enum HttpStatus {
  OK = 200,
  Created = 201,
  BadRequest = 400,
  Unauthorized = 401,
  NotFound = 404,
  InternalServerError = 500,
}

function handleHttpResponse(status: number): void {
  if (status === HttpStatus.OK) {
    console.log("Request berhasil");
  } else if (status === HttpStatus.NotFound) {
    console.log("Resource tidak ditemukan");
  } else if (status >= HttpStatus.BadRequest) {
    console.log("Terjadi error");
  }
}

handleHttpResponse(HttpStatus.OK); // "Request berhasil"
handleHttpResponse(HttpStatus.NotFound); // "Resource tidak ditemukan"

Dalam beberapa kasus, union type dari literal values bisa menjadi alternatif yang lebih baik daripada enum, terutama jika kita ingin pendekatan yang lebih functional.

/** Menggunakan enum */
enum Theme {
  Light,
  Dark,
  System,
}

/** Menggunakan union type */
type ThemeType = "light" | "dark" | "system";

/** Fungsi dengan enum */
function setThemeEnum(theme: Theme): void {
  // implementasi
}

/** Fungsi dengan union type */
function setThemeUnion(theme: ThemeType): void {
  // implementasi
}

// Penggunaan
setThemeEnum(Theme.Dark);
setThemeUnion("dark");

Union type memberikan type-safety yang sama dengan enum, tetapi dengan sintaks yang lebih sederhana dan tanpa perlu mendefinisikan tipe tambahan.

Kesimpulan

Optional properties dan optional chaining memberikan fleksibilitas dalam menangani data yang mungkin tidak lengkap, sementara enum menyediakan cara untuk mendefinisikan sekelompok konstanta terkait. Kedua fitur ini merupakan bagian penting dari sistem tipe TypeScript yang membantu kita menulis kode yang lebih aman, ekspresif, dan mudah dipelihara.

Dengan memahami dan memanfaatkan fitur-fitur ini, kita dapat mengembangkan aplikasi TypeScript yang lebih robust dan menghindari banyak bug yang biasanya muncul dalam pengembangan JavaScript biasa.

Konten Terkait