TypeScript untuk Pemula: Type Safety di JavaScript
TypeScript adalah superset dari JavaScript yang menambahkan static typing. Dengan TypeScript, kamu bisa menangkap error lebih awal dan menulis kode yang lebih maintainable.
Mengapa TypeScript?
- Catch errors at compile time: Temukan bug sebelum runtime
- Better IDE support: Autocomplete dan refactoring lebih baik
- Self-documenting code: Types sebagai dokumentasi
- Easier refactoring: Perubahan lebih aman
Setup TypeScript
Instalasi
# Global
npm install -g typescript
# Per project
npm install --save-dev typescript
Inisialisasi
npx tsc --init
Ini akan membuat tsconfig.json:
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"strict": true,
"outDir": "./dist",
"rootDir": "./src"
}
}
Compile
npx tsc # Compile semua
npx tsc --watch # Watch mode
Basic Types
Primitive Types
// String
let nama: string = 'John';
// Number
let umur: number = 25;
let harga: number = 99.99;
// Boolean
let aktif: boolean = true;
// Null dan Undefined
let kosong: null = null;
let belumAda: undefined = undefined;
Arrays
// Array of strings
let fruits: string[] = ['apple', 'banana', 'orange'];
// Alternative syntax
let numbers: Array<number> = [1, 2, 3];
// Mixed array (tuple)
let person: [string, number] = ['John', 25];
Objects
// Inline type
let user: { name: string; age: number } = {
name: 'John',
age: 25,
};
// Optional property
let config: { host: string; port?: number } = {
host: 'localhost',
};
Any dan Unknown
// Any - hindari jika memungkinkan
let data: any = 'hello';
data = 123; // OK, tapi tidak aman
// Unknown - lebih aman dari any
let input: unknown = 'hello';
if (typeof input === 'string') {
console.log(input.toUpperCase()); // OK setelah type check
}
Interfaces dan Types
Interface
interface User {
id: number;
name: string;
email: string;
age?: number; // Optional
readonly createdAt: Date; // Read-only
}
const user: User = {
id: 1,
name: 'John',
email: 'john@example.com',
createdAt: new Date(),
};
Type Alias
type ID = string | number;
type Point = {
x: number;
y: number;
};
type Status = 'pending' | 'approved' | 'rejected';
Interface vs Type
// Interface - bisa di-extend
interface Animal {
name: string;
}
interface Dog extends Animal {
breed: string;
}
// Type - bisa union/intersection
type Cat = Animal & { color: string };
type Pet = Dog | Cat;
Functions
Basic Function Types
// Parameter dan return type
function add(a: number, b: number): number {
return a + b;
}
// Arrow function
const multiply = (a: number, b: number): number => a * b;
// Optional parameter
function greet(name: string, greeting?: string): string {
return `${greeting || 'Hello'}, ${name}!`;
}
// Default parameter
function createUser(name: string, role: string = 'user'): void {
console.log(`Created ${role}: ${name}`);
}
Function Types
// Type untuk function
type MathOperation = (a: number, b: number) => number;
const subtract: MathOperation = (a, b) => a - b;
// Callback
function processData(data: string[], callback: (item: string) => void): void {
data.forEach(callback);
}
Union dan Intersection Types
Union Types
// Bisa salah satu type
type StringOrNumber = string | number;
function printId(id: StringOrNumber): void {
if (typeof id === 'string') {
console.log(id.toUpperCase());
} else {
console.log(id);
}
}
// Literal union
type Direction = 'up' | 'down' | 'left' | 'right';
Intersection Types
interface HasName {
name: string;
}
interface HasAge {
age: number;
}
// Gabungan kedua interface
type Person = HasName & HasAge;
const person: Person = {
name: 'John',
age: 25,
};
Generics
Basic Generics
// Generic function
function identity<T>(value: T): T {
return value;
}
const str = identity<string>('hello');
const num = identity<number>(42);
// Type inference
const inferred = identity('hello'); // T = string
Generic Interfaces
interface ApiResponse<T> {
data: T;
status: number;
message: string;
}
interface User {
id: number;
name: string;
}
const response: ApiResponse<User> = {
data: { id: 1, name: 'John' },
status: 200,
message: 'Success',
};
Generic Constraints
interface HasLength {
length: number;
}
function logLength<T extends HasLength>(item: T): void {
console.log(item.length);
}
logLength('hello'); // OK
logLength([1, 2, 3]); // OK
logLength({ length: 5 }); // OK
// logLength(123); // Error: number tidak punya length
Classes
class User {
// Properties
private id: number;
public name: string;
protected email: string;
readonly createdAt: Date;
// Constructor
constructor(id: number, name: string, email: string) {
this.id = id;
this.name = name;
this.email = email;
this.createdAt = new Date();
}
// Method
public greet(): string {
return `Hello, ${this.name}!`;
}
// Getter
get userId(): number {
return this.id;
}
}
// Inheritance
class Admin extends User {
private permissions: string[];
constructor(id: number, name: string, email: string, permissions: string[]) {
super(id, name, email);
this.permissions = permissions;
}
hasPermission(permission: string): boolean {
return this.permissions.includes(permission);
}
}
Utility Types
TypeScript menyediakan utility types bawaan:
interface User {
id: number;
name: string;
email: string;
password: string;
}
// Partial - semua property jadi optional
type PartialUser = Partial<User>;
// Required - semua property jadi required
type RequiredUser = Required<PartialUser>;
// Pick - ambil property tertentu
type UserPreview = Pick<User, 'id' | 'name'>;
// Omit - hilangkan property tertentu
type PublicUser = Omit<User, 'password'>;
// Readonly - semua property jadi readonly
type ImmutableUser = Readonly<User>;
// Record - object dengan key dan value type tertentu
type UserRoles = Record<string, string[]>;
Type Guards
// typeof guard
function processValue(value: string | number): void {
if (typeof value === 'string') {
console.log(value.toUpperCase());
} else {
console.log(value.toFixed(2));
}
}
// instanceof guard
class Dog {
bark() {
console.log('Woof!');
}
}
class Cat {
meow() {
console.log('Meow!');
}
}
function makeSound(animal: Dog | Cat): void {
if (animal instanceof Dog) {
animal.bark();
} else {
animal.meow();
}
}
// Custom type guard
interface Fish {
swim: () => void;
}
interface Bird {
fly: () => void;
}
function isFish(pet: Fish | Bird): pet is Fish {
return (pet as Fish).swim !== undefined;
}
Async/Await dengan Types
interface User {
id: number;
name: string;
}
// Async function dengan return type
async function fetchUser(id: number): Promise<User> {
const response = await fetch(`/api/users/${id}`);
return response.json();
}
// Error handling
async function safeGetUser(id: number): Promise<User | null> {
try {
return await fetchUser(id);
} catch {
return null;
}
}
Tips Best Practices
1. Aktifkan Strict Mode
{
"compilerOptions": {
"strict": true
}
}
2. Hindari any
// ❌ Bad
function process(data: any) {}
// ✅ Good
function process<T>(data: T) {}
3. Gunakan Type Inference
// ❌ Redundant
const name: string = 'John';
// ✅ Let TypeScript infer
const name = 'John';
4. Export Types
// types.ts
export interface User {
id: number;
name: string;
}
export type Status = 'active' | 'inactive';
Kesimpulan
TypeScript memberikan banyak keuntungan:
- Error detection lebih awal
- IDE support yang lebih baik
- Kode lebih maintainable
- Dokumentasi otomatis melalui types
Mulai dengan basic types, lalu pelajari generics dan utility types sesuai kebutuhan.
Referensi:
Komentar
Memuat komentar...
Tulis Komentar