Jika Anda seorang Laravel developer yang terbiasa dengan PHP yang strongly typed, beralih ke JavaScript murni seringkali terasa seperti mundur: tidak ada type hints, tidak ada IDE autocomplete yang reliable, dan bug yang seharusnya terdeteksi saat coding baru ketahuan saat runtime. TypeScript hadir untuk menyelesaikan frustrasi ini — membawa type system ke ekosistem JavaScript tanpa mengorbankan fleksibilitasnya.
Mengapa TypeScript Terasa Natural untuk PHP Developer
Jika Anda sudah nyaman dengan PHP 8.x, sebagian besar konsep TypeScript sudah familiar:
| PHP | TypeScript |
|---|---|
string $name | name: string |
?string $name | name: string | null |
array $items | items: string[] atau Array<string> |
interface Renderable | interface Renderable |
readonly string $id | readonly id: string |
Perbedaan utama: TypeScript memiliki tipe any sebagai escape hatch (hindari sebisa mungkin), dan type inference yang sangat canggih sehingga Anda tidak harus annotate semuanya secara manual.
Setup TypeScript di Project Laravel + Vite
npm install -D typescript @types/node
# Buat tsconfig.json
npx tsc --init
// tsconfig.json (konfigurasi untuk Laravel + Vite)
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"jsx": "preserve",
"baseUrl": ".",
"paths": {
"@/*": ["resources/js/*"]
},
"types": ["vite/client", "node"]
},
"include": ["resources/js/**/*.ts", "resources/js/**/*.vue"]
}
// vite.config.js — rename ke vite.config.ts dan update
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [
laravel({ input: ['resources/js/app.ts'], refresh: true }),
vue(),
],
});
Dasar-dasar yang Perlu Dikuasai
Types dan Interfaces
// Type alias — cocok untuk union types dan simple types
type Status = 'draft' | 'published' | 'archived';
type ID = number | string;
// Interface — cocok untuk shape objek, bisa di-extend
interface Post {
id: number;
title: string;
slug: string;
status: Status;
author: User;
published_at: string | null;
categories: Category[];
}
interface User {
id: number;
name: string;
email: string;
avatar_url: string | null;
}
// Extend interface
interface AdminPost extends Post {
view_count: number;
edit_url: string;
}
Generic Types
Generic memungkinkan komponen yang reusable dengan type safety:
// Respons API yang konsisten
interface ApiResponse<T> {
data: T;
message: string;
success: boolean;
}
interface PaginatedResponse<T> {
data: T[];
current_page: number;
last_page: number;
total: number;
per_page: number;
}
// Penggunaan
async function fetchPosts(): Promise<PaginatedResponse<Post>> {
const res = await fetch('/api/posts');
return res.json();
}
const response: ApiResponse<User> = await loginUser(credentials);
Utility Types yang Sering Dipakai
// Partial — semua field menjadi optional (cocok untuk update form)
type UpdatePostDto = Partial<Post>;
// Pick — ambil hanya field tertentu
type PostCard = Pick<Post, 'id' | 'title' | 'slug' | 'excerpt'>;
// Omit — hilangkan field tertentu
type CreatePostDto = Omit<Post, 'id' | 'author' | 'published_at'>;
// Required — semua field menjadi required
type PublishedPost = Required<Post>;
// Record — untuk objek dengan key dinamis
type PostsBySlug = Record<string, Post>;
TypeScript dengan Inertia.js (Laravel + Vue)
// resources/js/types/index.d.ts
export interface PageProps {
auth: {
user: User | null;
};
flash: {
success?: string;
error?: string;
};
}
// Di komponen Vue
import { usePage } from '@inertiajs/vue3';
import type { PageProps } from '@/types';
const page = usePage<PageProps>();
const user = computed(() => page.props.auth.user);
// user sekarang fully typed!
Tips Migrasi Bertahap
Tidak perlu konversi semua file sekaligus. TypeScript bisa hidup berdampingan dengan JavaScript:
- Rename file satu per satu dari
.jske.ts - Mulai dengan
"strict": false, aktifkan secara bertahap - Buat file
types/index.d.tsuntuk type definisi global - Gunakan
// @ts-ignoresementara untuk error yang belum sempat diperbaiki - Perbaiki error satu per satu, jangan semua sekaligus
Investasi belajar TypeScript biasanya terbayar dalam 2-3 minggu: setelah itu, Anda akan jarang menghabiskan waktu debugging error yang seharusnya bisa terdeteksi IDE, dan autocomplete yang akurat membuat coding lebih cepat secara keseluruhan.