TypeScript dành cho React: Những điều cần biết

0 0 0

Người đăng: Vũ Tuấn

Theo Viblo Asia

Nếu bạn là một lập trình viên React và vẫn đang dùng JavaScript, thì bạn đang tự làm khó mình đấy.

Thời gian bạn dành ra để học TypeScript chắc chắn sẽ được “hoàn vốn” bằng thời gian tiết kiệm được khi debug những lỗi kỳ quặc.

Vì vậy, đây là một hướng dẫn giúp bạn chuyển sang TypeScript.

Chỉ những thứ thiết yếu. Không vòng vo 😉. Hãy cùng bắt đầu nhé!

Cách TypeScript hoạt động

TypeScript bổ sung cú pháp cho JavaScript để giúp phát hiện lỗi sớm — trước khi chúng làm crash ứng dụng của bạn.

Cuối cùng thì nó vẫn được biên dịch ra JavaScript.

Phần hay nhất? Bạn có thể từng bước chuyển sang TypeScript.

Tại sao bạn nên chuyển sang TypeScript càng sớm càng tốt

Dưới đây là lý do tại sao mình nghĩ việc này là “không cần suy nghĩ nhiều”:

Lợi ích #1: Bắt lỗi trước khi lên production

Đoạn code JavaScript này nhìn có vẻ ổn… cho đến khi nó khiến bạn phát rồ:

function printFirstChar(users, userIndex) { const name = users[userIndex]; console.log(name[0]);
} const users = ['Fatou', 'Bob']; printFirstChar(users, 5); // ❌ Runtime error: Cannot read properties of undefined

Còn đây là phiên bản TypeScript:

function printFirstChar(users: string[], userIndex: number) { const name = users[userIndex]; if (name != null) { console.log(name[0]); }
}

TypeScript không sửa logic cho bạn, nhưng nó sẽ cảnh báo sớm kiểu như “này, cái này có thể là undefined đó”.

Lợi ích #2: Tự động gợi ý khi dùng thư viện

Đặc biệt hữu ích khi bạn đang khám phá một thư viện mới.

Nếu thư viện đó có định nghĩa kiểu TypeScript, bạn sẽ được gợi ý tự động ngay trong hầu hết các editor.

Lợi ích #3: Làm cho code vững chắc hơn khi có thay đổi

Khi bạn định kiểu đúng cách, TypeScript giống như một chiếc lưới an toàn.

Ví dụ: Nếu không dùng TypeScript, đoạn code này có thể bị lỗi mà bạn không phát hiện:

function getLabel(status) { switch (status) { case 'idle': return 'Idle'; case 'loading': return 'Loading'; case 'success': return 'Success'; }
} getLabel('loading'); // ✅ works // Months later... getLabel('error'); // ❌ returns undefined, but no JS error

Với TypeScript, bạn phải xử lý mọi thay đổi.

type Status = 'idle' | 'loading' | 'success'; function getLabel(status: Status): string { switch (status) { case 'idle': return 'Idle'; case 'loading': return 'Loading'; case 'success': return 'Success'; case 'error': return 'Error'; }
} // Months later...
type Status = 'idle' | 'loading' | 'success' | 'error'; // added 'error' // ✅ TypeScript will show an error for the `getLabel` function: "Not all code paths return a value"

Nếu bạn quên xử lý một case, TypeScript sẽ “la làng”. Và đó chính là điều bạn muốn 😄.

Các khái niệm TypeScript cần biết khi dùng với React

Hãy bắt đầu với những khái niệm tối thiểu cần thiết để làm việc.

✅ Kiểu dữ liệu (Types)

Kiểu dữ liệu cho phép bạn mô tả hình dạng (shape) của dữ liệu và ép buộc nó theo đúng định nghĩa.

Trong TypeScript có kiểu dữ liệu gốc (native types) và kiểu do người dùng định nghĩa.

1. Kiểu gốc (Native types)

Đây là các kiểu được cung cấp sẵn trong TypeScript:

const name = 'Ada'; // string
const age: number = 31; // number
const isActive = true; // boolean
const scores: number[] = [90, 85, 100]; // number[]

Trong một số ví dụ trên, mình khai báo kiểu dữ liệu một cách tường minh (như const age: number = 31).

Bạn không cần phải làm vậy trong thực tế — TypeScript có thể suy luận kiểu dữ liệu dựa vào giá trị gán.

2. Kiểu tùy chỉnh (Custom types)

Bạn có thể tạo kiểu mới bằng cách kết hợp các kiểu gốc:

type User = { id: number; name: string;
}; const user: User = { id: 1, name: 'Fatou',
};

❌ Tránh dùng any

Trừ khi bạn đang trong quá trình chuyển đổi dự án cũ sang TS, đừng dùng any.

Về cơ bản, any là JavaScript trá hình.

Thay vào đó, hãy dùng unknown — nó bắt buộc bạn phải kiểm tra kiểu trước khi sử dụng.

// ❌ Bad: no warning, crashes at runtime
function logLength(value: any) { console.log(value.length);
} logLength(123); // ✅ Safer
function logLength(value: unknown) { if (typeof value === 'string' || Array.isArray(value)) { console.log(value.length); }
} // ✅✅ Better: use an explicit type
function logLength(value: string | ArrayLike<unknown>){ console.log(value.length);
}

🧩 Union & Intersection types

Union cho phép một giá trị là một trong nhiều kiểu:

type Status = 'idle' | 'loading' | 'error'; let currentStatus: Status = 'idle';

Intersection kết hợp nhiều kiểu thành một kiểu duy nhất:

type Name = { name: string };
type Age = { age: number }; type Person = Name & Age; const person: Person = { name: 'Ada', age: 30 };

🧱 Interfaces

Interface định nghĩa cấu trúc của một đối tượng:

interface User { name: string; age: number;
}

Bạn cũng có thể kế thừa interface:

interface Admin extends User { role: string;
}

Nên dùng type hay interface? → Không quá quan trọng.

🔁 Generics

Generics cho phép bạn tạo các kiểu có thể tái sử dụng và linh hoạt.

Ví dụ: bạn đang định nghĩa phản hồi từ một API.

Không dùng generics:

type UserResponse = { status: number; data: User; error?: string;
}; type ProductResponse = { status: number; data: Product; error?: string;
};

=> Quá nhiều lặp lại.

Dùng generics:

type ApiResponse<T> = { status: number; data: T; error?: string;
}; type UserResponse = ApiResponse<User>;
type ProductResponse = ApiResponse<Product>;

Bạn cũng có thể dùng generics trong function:

function wrap<T>(value: T): T[] { return [value];
} wrap(42); // type: number[]
wrap('hi'); // type: string[]

Mình thường nghĩ Generics giống như tham số của hàm — nhưng dành cho kiểu dữ liệu 😉

🔧 Kiểu cho hàm (Function types)

Bạn có thể định kiểu cho tham số và giá trị trả về của hàm.

Bạn phải định kiểu cho tham số, nhưng giá trị trả về có thể để TypeScript tự suy luận.

// This works
function add(a: number, b: number): number { return a + b;
} // This also works: you don't need to type the returned value
function add(a: number, b: number) { return a + b; // inferred as number
}

Bạn cũng có thể định kiểu cho biến hàm:

const add: (a: number, b: number) => number = (a, b) => a + b;

Tuỳ từng tình huống, bạn có thể cần định kiểu cho return type. Khi không chắc chắn, hãy định kiểu cho giá trị trả về.

Cách sử dụng TypeScript với React

🔸 Props

Props chỉ đơn giản là các đối tượng. Bạn có thể định kiểu cho chúng như bất kỳ object nào khác.

Dùng type:

type GreetingProps = { name: string;
}; function Greeting({ name }: GreetingProps) { return <p>Hello {name}</p>;
}

Dùng interface:

interface GreetingProps { name: string;
} function Greeting({ name }: GreetingProps) { return <p>Hello {name}</p>;
}

🔸 State

useState chấp nhận kiểu generic, nhưng TypeScript thường có thể suy luận kiểu một cách tự động:

const [count, setCount] = useState(0); // inferred as number

Nhưng nếu TS không thể đoán được kiểu, bạn nên khai báo rõ ràng:

const [user, setUser] = useState<{ id: number; name: string } | null>(null);

🔸 Biến và hàm trong component

Giống như viết TypeScript bình thường:

const users: User[] = [{name: "Fatou", age: 31}, {name: "Bob", age: 25} ];
const age = 30; // inferred as number

Khi bạn viết các hàm xử lý sự kiện như onClick, hãy di chuột lên phần tử DOM để xem kiểu phù hợp:

const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => { console.log('Clicked!', event);
}; // Or:
const handleClick: React.MouseEventHandler<HTMLButtonElement> = (event) => { console.log('Clicked!', event);
};

🔸 Tái sử dụng kiểu dữ liệu giữa các components

Bạn có thể mở rộng hoặc kết hợp các type hoặc interface để tránh lặp lại.

Dùng interface:

interface ButtonProps { label: string;
} interface IconButtonProps extends ButtonProps { icon: React.ReactNode;
}

Dùng union với type:

type ButtonProps = { label: string;
}; type IconButtonProps = ButtonProps & { icon: React.ReactNode;
};

🔸 Hooks

Hooks chỉ là các hàm, nên bạn có thể áp dụng các kỹ thuật TypeScript giống như với hàm thông thường.

1. Hooks có sẵn trong React:

const [count, setCount] = useState<number>(0);
// or let TS infer:
const [count, setCount] = useState(0); const inputRef = useRef<HTMLInputElement>(null); const [state, dispatch] = useReducer( (state: number, action: 'inc' | 'dec') => { switch (action) { case 'inc': return state + 1; case 'dec': return state - 1; } }, 0
);

2. Hooks tùy chỉnh (Custom hooks)

function useToggle(initial: boolean): [boolean, () => void] { const [state, setState] = useState(initial); const toggle = () => setState((prev) => !prev); return [state, toggle];
} const [isOpen, toggleOpen] = useToggle(false);

📚 Tài nguyên học TypeScript chuyên sâu

Nếu bạn muốn học sâu hơn về TypeScript, dưới đây là một số nguồn cực kỳ hữu ích:

🧠 TypeScript Official Docs: Tài liệu chính thức từ TS. Rất rõ ràng, có cấu trúc tốt, nhiều ví dụ, và có playground để thử nghiệm.

🎯 Total TypeScript (của Matt Pocock): Một trang cực kỳ hay, đặc biệt cho lập trình viên React. Có khóa học miễn phí, ví dụ thực tế và các pattern nâng cao.

TypeScript Style Guide: Hướng dẫn ngắn gọn, thực tế để viết code TypeScript sạch và đồng nhất. Rất hữu ích khi bạn bắt đầu build app thực tế.

🧩 Type Challenges: Tập hợp các bài tập TypeScript từ dễ đến “căng não”. Rất phù hợp với những ai học bằng cách giải bài và muốn nâng cấp kỹ năng type system.

📘 Effective TypeScript (sách + blog của Dan Vanderkam): Dành cho người đã có nền tảng TS. Dạy cách viết code TS tốt hơn và tránh lỗi thường gặp.

⚛️ React TypeScript Cheatsheets: Là bí kíp “gối đầu giường” cho dev React. Bao phủ từ components, context, đến hooks. Rất dễ tiếp cận và tiện tra cứu nhanh.

Kết luận

Sử dụng TypeScript với React là một trong những nâng cấp đáng giá nhất mà bạn có thể thực hiện.

Nó giúp bạn phát hiện lỗi sớm, có công cụ hỗ trợ lập trình tốt hơn, và khiến code dễ bảo trì hơn.

Điều tuyệt vời nhất? Bạn không cần học tất cả mọi thứ ngay từ đầu. Hãy bắt đầu với những nền tảng cơ bản như:

types, interfaces, generics — và dần dần phát triển thêm.

Có rất nhiều ví dụ trên mạng nếu bạn gặp khó khăn, và các công cụ AI cũng có thể giúp bạn nhanh chóng vượt qua các trở ngại.

Nếu bạn có bất kỳ câu hỏi nào, cứ hỏi mình nhé 🙂.

Bình luận

Bài viết tương tự

- vừa được xem lúc

Giới thiệu Typescript - Sự khác nhau giữa Typescript và Javascript

Typescript là gì. TypeScript là một ngôn ngữ giúp cung cấp quy mô lớn hơn so với JavaScript.

0 0 539

- vừa được xem lúc

Type annotation vs Type Inference - Typescript

Trong bài viết này, chúng ta sẽ tìm hiểu kỹ về TypeScript bằng cách tìm hiểu sự khác biệt giữa kiểu chú thích và kiểu suy luận. Tôi sẽ cho rằng bạn có một số kinh nghiệm về JavaScript và biết về các kiểu cơ bản, như chuỗi, số và boolean.

0 0 55

- vừa được xem lúc

Type Annotation và Type Inference trong TypeScript là gì?

Khi làm việc với javascript chắc hẳn các bạn đã quá quen với việc dùng biến mà không cần phải quan tâm đến kiểu dữ liệu của nó là gì phải không? Đúng là mới đầu tiếp cận với Typescript mình cũng cảm thấy nó khá là phiền vì cần phải khai báo đủ type để nó chặt chẽ hơn. Lúc đó mình còn nghĩ: " JavaScr

0 0 42

- vừa được xem lúc

Tìm hiểu TypeScript và kiến thức cơ bản

TypeScript là gì. TypeScript sử dụng tất cả các tính năng của của ECMAScript 2015 (ES6) như classes, modules.

0 0 58

- vừa được xem lúc

TypeScript - P1: Vì sao TypeScript được yêu thích đến vậy?

Trải nghiệm thực tế. Trước khi là một Web Developer, tôi là một Mobile Developer và Java là thứ mà tôi từng theo đuổi.

0 1 72

- vừa được xem lúc

4 Tính năng rất hay từ TypeScript

Xin chào các bạn hôm nay mình xin chia sẽ những tính năng rất hay của TypeScript (TS), các bạn cùng tìm hiểu nhé. Ngoài việc set Type cho biến, tham số hay function thì ví dụ khi bạn nhìn vào một tham

0 0 98