Berkenalan dengan TypeScript

TypeScript adalah bahasa pemrograman yang dibangun di atas JavaScript. Bahasa ini menambahkan fitur-fitur baru seperti tipe statis, kelas, dan interface yang tidak tersedia di JavaScript. Dengan TypeScript, kita dapat menangkap error lebih awal dalam proses pengembangan, sehingga lebih mudah dalam melakukan pemeliharaan aplikasi. Penulisan kode pada Typescript lebih ketat terhadap tipe data, aturan ini membantu dalam mendeteksi bug sebelum kode dijalankan.

Menyiapkan Environment Pengembangan

Untuk mulai menggunakan TypeScript, kita perlu menyiapkan:

  1. Node.js: Unduh dan instal Node.js dari nodejs.org. Node.js menyediakan runtime untuk menjalankan JavaScript di server dan menyertakan npm (Node Package Manager) untuk mengelola dependensi.

  2. TypeScript: Buka terminal dan jalankan perintah npm install -g typescript untuk menginstal TypeScript secara global pada sistem.

  3. Code Editor: Gunakan code editor yang mendukung TypeScript.

Mulai Menulis Program TypeScript

Setelah mengatur environment, kita sudah bisa menulis kode TypeScript. Misalnya kita buat file hello.ts. Ketik kode berikut:

let message: string = "Hello, TypeScript!";
console.log(message);

Penjelasan:

  • Deklarasi Variabel: let message: string mendeklarasikan variabel message dengan tipe string.

  • Inisialisasi Variabel: message = "Hello, TypeScript!" menginisialisasi variabel dengan nilai string.

  • Output ke Konsol: console.log(message) mencetak nilai message ke konsol.

Kompilasi kode dengan menjalankan tsc hello.ts di terminal, yang akan menghasilkan file hello.js. Jalankan file JavaScript ini menggunakan Node.js dengan perintah node hello.js.

Mengonfigurasi TypeScript Compiler

Buat file konfigurasi tsconfig.json di root proyek kita dengan menjalankan tsc --init di terminal. Ini akan menghasilkan file dengan pengaturan default. Kita dapat menyesuaikan pengaturan ini sesuai kebutuhan proyek kita.

Contoh tsconfig.json:

{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true
  }
}

Penjelasan:

  • target: Menentukan versi JavaScript yang dihasilkan (misalnya, ES6).

  • module: Menentukan sistem modul (misalnya, CommonJS).

  • outDir: Direktori keluaran untuk file JavaScript yang dikompilasi.

  • rootDir: Direktori sumber untuk file TypeScript.

  • strict: Mengaktifkan pemeriksaan tipe ketat.

  • esModuleInterop: Memungkinkan interoperabilitas dengan modul ES.

Debugging Aplikasi TypeScript

Untuk debugging, aktifkan source map dalam tsconfig.json:

{
  "compilerOptions": {
    "sourceMap": true
  }
}

Gunakan VS Code untuk menambahkan breakpoint dan menjalankan debugging. Ini memungkinkan kode untuk mengeksekusi kode baris demi baris dan memeriksa nilai dari variabel.

Langkah-langkah debugging:

  1. Buka file index.ts di VS Code.

  2. Tambahkan breakpoint dengan mengklik di sebelah nomor baris.

  3. Buka terminal terintegrasi di VS Code (View > Terminal).

  4. Jalankan tsc -w untuk mengompilasi TypeScript secara otomatis saat file diubah.

  5. Mulai debugging dengan membuka tab Debug (View > Debug) dan klik tombol play (▶️).

Built-in Types dalam TypeScript

Tipe Dasar

TypeScript mendukung semua tipe dasar yang ada di JavaScript seperti:

Number: Digunakan untuk merepresentasikan angka baik integer maupun floating-point. Contoh:

let decimal: number = 6;
let hex: number = 0xf00d;
let binary: number = 0b1010;
let octal: number = 0o744;

String: Digunakan untuk merepresentasikan teks. String dapat diapit dengan tanda kutip tunggal ('), kutip ganda ("), atau backticks (` ). Contoh:

let color: string = "blue";
let fullName: string = `John Doe`;

Boolean: Digunakan untuk merepresentasikan nilai benar atau salah. Contoh:

let isDone: boolean = false;

Array: TypeScript mendukung tipe array yang dapat dideklarasikan dengan dua cara: menggunakan tanda kurung siku ([]) atau dengan menggunakan generik Array<elemType>. Contoh:

let list: number[] = [1, 2, 3];
let list: Array<number> = [1, 2, 3];

Tuple: Tuple adalah array dengan panjang tetap di mana tiap elemen dapat memiliki tipe yang berbeda. Contoh:

let x: [string, number];
x = ["hello", 10]; // benar
x = [10, "hello"]; // salah

Enum: Enums memungkinkan kita mendefinisikan satu set nilai yang diberi nama. Contoh:

enum Color {Red, Green, Blue}
let c: Color = Color.Green;

Any: Tipe any digunakan ketika kita tidak tahu tipe pasti dari suatu variabel. Ini menonaktifkan pemeriksaan tipe, membuat variabel dapat menampung nilai apapun. Contoh:

let notSure: any = 4;
notSure = "maybe a string instead";
notSure = false;

Void: Tipe void biasanya digunakan sebagai tipe kembalian dari fungsi yang tidak mengembalikan nilai. Contoh:

function warnUser(): void {
    console.log("This is my warning message");
}

Null dan Undefined: TypeScript memiliki tipe null dan undefined yang sebenarnya merupakan subtipe dari semua tipe lain. Ini berarti kita bisa menetapkan null dan undefined ke variabel dengan tipe lain. Contoh:

let u: undefined = undefined;
let n: null = null;

Never: Tipe never adalah tipe untuk nilai yang tidak akan pernah terjadi. Misalnya, fungsi yang selalu melempar pengecualian atau tidak pernah kembali memiliki tipe kembalian never. Contoh:

function error(message: string): never {
    throw new Error(message);
}

function fail() {
    return error("Something failed");
}

function infiniteLoop(): never {
    while (true) {}
}

Functions dalam TypeScript

Fungsi adalah blok kode yang dirancang untuk melakukan tugas tertentu. Di TypeScript, fungsi dapat diberi tipe untuk parameter dan nilai kembalian, memberikan kontrol lebih besar terhadap tipe data yang digunakan.

Deklarasi Fungsi

Fungsi di TypeScript dideklarasikan sama seperti di JavaScript, tetapi kita bisa menambahkan tipe untuk parameter dan nilai kembalian.

function add(x: number, y: number): number {
    return x + y;
}

Fungsi Anonim

Fungsi anonim adalah fungsi tanpa nama yang sering digunakan sebagai argumen untuk fungsi lain.

let myAdd = function(x: number, y: number): number { 
    return x + y; 
};

Fungsi Panah (Arrow Functions)

Fungsi panah adalah cara yang lebih ringkas untuk menulis fungsi anonim. Sintaksnya mirip dengan lambda di banyak bahasa pemrograman Python.

let myAdd = (x: number, y: number): number => x + y;

Tipe untuk Parameter dan Nilai Kembalian

Kita dapat menentukan tipe untuk parameter dan nilai kembalian fungsi. Jika kita tidak menentukan tipe nilai kembalian, TypeScript akan mencoba untuk menyimpulkan dari pernyataan return.

function greet(name: string): string {
    return `Hello, ${name}`;
}

Parameter Opsional dan Default

Kita dapat membuat parameter opsional dengan menambahkan tanda tanya (?) setelah nama parameter. Kita juga dapat menetapkan nilai default untuk parameter.

function buildName(firstName: string, lastName?: string): string {
    if (lastName) return firstName + " " + lastName;
    else return firstName;
}

function buildNameWithDefault(firstName: string, lastName: string = "Smith"): string {
    return firstName + " " + lastName;
}

Parameter Sisa (Rest Parameters)

Parameter sisa memungkinkan kita untuk menyimpan sejumlah argumen sebagai array.

function buildName(firstName: string, ...restOfName: string[]): string {
    return firstName + " " + restOfName.join(" ");
}

Overloading

TypeScript mendukung overloading fungsi. Kita dapat menulis beberapa deklarasi fungsi untuk satu implementasi fungsi.

function pickCard(x: { suit: string; card: number; }[]): number;
function pickCard(x: number): { suit: string; card: number; };
function pickCard(x): any {
    if (typeof x == "object") {
        return Math.floor(Math.random() * x.length);
    } else if (typeof x == "number") {
        return { suit: "hearts", card: x % 13 };
    }
}

Objects dalam TypeScript

Objek adalah koleksi nilai yang berpasangan dengan kunci (key-value pairs). TypeScript memperluas konsep objek di JavaScript dengan menambahkan tipe yang ketat.

Deklarasi Objek

Objek dideklarasikan sama seperti di JavaScript, tetapi kita bisa menentukan tipe untuk setiap properti.

let person: { name: string, age: number } = {
    name: "John",
    age: 30
};

Tipe Objek

Kita dapat mendefinisikan tipe untuk objek agar lebih mudah digunakan kembali.

type Person = {
    name: string;
    age: number;
};

let john: Person = {
    name: "John",
    age: 30
};

Properti Opsional

Kita dapat membuat properti opsional dengan menambahkan tanda tanya (?) setelah nama properti.

type Person = {
    name: string;
    age?: number;
};

let john: Person = {
    name: "John"
};

Properti Read-Only

Properti readonly hanya dapat diinisialisasi sekali, baik pada saat deklarasi atau di dalam konstruktor kelas.

type Person = {
    readonly id: number;
    name: string;
    age?: number;
};

let john: Person = {
    id: 1,
    name: "John"
};

// john.id = 2; // Error: Cannot assign to 'id' because it is a read-only property.

Fungsi dalam Objek

Kita juga dapat menentukan fungsi di dalam objek.

type Person = {
    name: string;
    age?: number;
    greet(): string;
};

let john: Person = {
    name: "John",
    greet() {
        return `Hello, my name is ${this.name}`;
    }
};

console.log(john.greet()); // Output: Hello, my name is John

Tipe Index Signatures

Tipe index signatures memungkinkan kita membuat objek dengan jumlah properti yang tidak diketahui, tetapi dengan tipe kunci dan nilai tertentu.

interface StringArray {
    [index: number]: string;
}

let myArray: StringArray;
myArray = ["Bob", "Fred"];

let myStr: string = myArray[0];

Advanced Types dalam TypeScript

Type Aliases

Type Aliases memungkinkan kita untuk membuat nama baru untuk tipe yang ada. Ini sangat berguna untuk merujuk ke tipe yang kompleks atau panjang dengan cara yang lebih sederhana dan lebih mudah dibaca.

Contoh:

type Point = {
    x: number;
    y: number;
};

let point: Point = { x: 10, y: 20 };

Dalam contoh di atas, Point adalah alias untuk objek dengan dua properti x dan y, yang keduanya adalah number. Kita dapat menggunakan Point sebagai tipe di mana saja di kode Anda.

Union Types

Union Types memungkinkan kita untuk menetapkan beberapa tipe ke sebuah variabel. Variabel dengan union type dapat menyimpan nilai dari salah satu tipe yang ditentukan.

Contoh:

let value: string | number;

value = "Hello";  // valid
value = 42;       // valid
// value = true; // Error: Type 'boolean' is not assignable to type 'string | number'.

Union types memungkinkan lebih banyak fleksibilitas saat bekerja dengan data yang bisa dalam beberapa bentuk yang berbeda.

Intersection Types

Intersection Types memungkinkan kita untuk menggabungkan beberapa tipe menjadi satu tipe. Objek yang memiliki intersection type harus memiliki semua properti dari semua tipe yang digabungkan.

Contoh:

type Draggable = {
    drag: () => void;
};

type Resizable = {
    resize: () => void;
};

type UIElement = Draggable & Resizable;

let uiElement: UIElement = {
    drag() {
        console.log("Dragging...");
    },
    resize() {
        console.log("Resizing...");
    }
};

Dalam contoh di atas, UIElement adalah intersection type dari Draggable dan Resizable. Objek uiElement harus memiliki metode drag dan resize.

Literal Types

Literal Types memungkinkan kita untuk menetapkan nilai spesifik sebagai tipe. Ini berguna untuk membatasi nilai yang bisa diambil oleh variabel.

Contoh:

type CardinalDirection = "North" | "East" | "South" | "West";

function move(direction: CardinalDirection) {
    console.log(`Moving ${direction}`);
}

move("North"); // valid
// move("Up"); // Error: Argument of type '"Up"' is not assignable to parameter of type 'CardinalDirection'.

Dengan literal types, kita dapat memastikan bahwa variabel hanya mengambil nilai tertentu yang telah ditentukan.

Nullable Types

Nullable Types memungkinkan variabel untuk memiliki nilai null atau undefined selain nilai dari tipe aslinya. TypeScript menyediakan cara untuk bekerja dengan tipe yang mungkin null atau undefined.

Contoh:

let name: string | null = "John";
name = null; // valid
// name = undefined; // Error: Type 'undefined' is not assignable to type 'string | null'.

Kita dapat menggunakan union types dengan null atau undefined untuk membuat tipe nullable.

Optional Chaining

Optional Chaining adalah fitur yang memungkinkan Anda untuk secara aman mengakses properti objek yang mungkin null atau undefined. Dengan optional chaining, kita dapat menghindari error saat mencoba mengakses properti dari objek null atau undefined.

Contoh:

type User = {
    address?: {
        street?: string;
    }
};

let user: User = {};

// Safe access using optional chaining
let street = user.address?.street;
console.log(street); // undefined

user = { address: { street: "Main St" } };
street = user.address?.street;
console.log(street); // "Main St"

Dengan menggunakan operator ?., kita dapat menghindari error yang terjadi jika mencoba mengakses properti dari objek yang undefined atau null.

Kesimpulan

TypeScript menyediakan fitur-fitur yang membantu dalam menulis kode yang lebih kuat, jelas, dan mudah dipelihara. Dengan memanfaatkan tipe statis, kita dapat mendeteksi kesalahan lebih awal dalam proses pengembangan, meningkatkan kehandalan dan pemeliharaan aplikasi. Menggunakan fitur seperti type aliases, union types, intersection types, literal types, nullable types, dan optional chaining, kita dapat menulis kode yang lebih aman dan mudah dipahami. Fungsi dan objek dalam TypeScript memberikan kontrol lebih besar terhadap tipe data yang digunakan, sehingga mengurangi jumlah bug dan meningkatkan kualitas kode secara keseluruhan. Semoga artikel ini bermanfaat, terima kasih dan selamat belajar.