TypeScript Deep Guide
Mở đầu
Đã biết JS, nhưng có thể đã gặp:
- Variable gán wrong type, runtime mới biết
- Tên property sai, debug mãi
- Function param type sai, sửa qua lại
TypeScript giúp phát hiện vấn đề này trước khi code chạy. Đọc xong, hiểu sao TS tăng code quality, đọc được type annotation, interface, generic, dùng tốt code AI gen trong vibecoding.
Bạn sẽ học:
| Chương | Nội dung |
|---|---|
| 1 | TS là gì |
| 2 | Type annotation cơ bản |
| 3 | Object type + Interface |
| 4 | Function type |
| 5 | Generic |
| 6 | Type inference + tips |
1. TypeScript là gì
Core
JS đã đủ dùng, sao cần TS? Học thêm syntax đáng không?
1.1 Từ "runtime error" → "compile-time detection"
| 🔴 JS pain | TS lợi |
|---|---|
| Runtime mới biết type error | Viết code đã biết error |
| Typo khó nhận | IDE suggest chính xác |
| Refactor dễ sót | Refactor an toàn |
| IDE hint không chính xác | Code dễ maintain |
| Tech | Ẩn dụ | Use |
|---|---|---|
| JS | Material thô | Code chạy trực tiếp |
| TS | Blueprint + QC | Thêm type check, cuối compile → JS |
1.2 Sao vibecoding cũng cần TS?
AI code cũng có thể sai
1 dev dùng AI gen feature quản user. AI viết JS chạy được, nhưng age user phải number, đôi khi bị gán string nhầm. Lúc tính "đã trưởng thành?", string "25" bị xử như string → judge fail. Bug ẩn lâu, đến khi user nhập ký tự không phải số mới lộ.
Nếu TS, lúc viết đã báo error: Type 'string' is not assignable to type 'number'.
Đây là giá trị TS — AI viết sai type, bạn biết ngay.
1.3 TS thực ra như thế nào
TS không phải ngôn ngữ mới, chỉ là superset của JS:
// JS valid = TS valid
const name = "Hoàng"
const age = 25
function greet(user) {
return `Hello ${user}`
}
// Đây là TS đặc trưng: type annotation
const name2: string = "Linh"
const age2: number = 30
function greet2(user: string): string {
return `Hello ${user}`
}Key:
- Mọi JS code = valid TS code
- TS thêm type annotation optional
- TS cuối compile thành JS
Insight
TS không đổi cách code chạy, chỉ help check type lúc compile. Có thể adopt TS gradual — bắt đầu add type cho key variable.
2. Type annotation cơ bản
2.1 Syntax
Type annotation = sau tên variable thêm : type:
// Syntax: name: type = value
const name: string = "Hoàng"
let age: number = 25
let isStudent: boolean = true📝 TypeScript 类型注解演示
const name: string = "张三"const age: number = 25const isActive: boolean = truelet name = "张三"
name = 123 // ✅ 运行时才会报错(可能很晚才发现)let name: string = "张三"
name = 123 // ❌ 编译时立即报错(写代码时就发现)Sao 1 số chỗ không cần annotation?
TS auto-infer từ giá trị:
const name = "Hoàng" // infer string
const age = 25 // infer number
const isActive = true // infer boolean
let data // ❌ Không infer được
let data: any // ✅ Được, nhưng mất type check
function add(a, b) { // ❌ Param type unclear
return a + b
}
function add2(a: number, b: number): number { // ✅
return a + b
}2.2 Basic types
| Type | Note | Vd |
|---|---|---|
string | String | "hello" |
number | Số (int + float) | 42, 3.14 |
boolean | True/False | true, false |
null / undefined | Null | null, undefined |
array | Array | number[], string[] |
object | Object | { name: string; age: number } |
Array 2 cách viết:
// Cách 1: type[] (hay dùng)
const numbers: number[] = [1, 2, 3]
const names: string[] = ["A", "B"]
// Cách 2: Array<type>
const numbers2: Array<number> = [1, 2, 3]Special types:
// any: bất kỳ (cẩn thận, = tắt type check)
let data: any = 42
data = "string"
data = { name: "Hoàng" }
// unknown: any type-safe
let value: unknown = 42
if (typeof value === "number") {
console.log(value + 10) // Phải check type trước
}
// void: không return
function log(message: string): void {
console.log(message)
}
// never: không bao giờ return
function error(message: string): never {
throw new Error(message)
}3. Object type + Interface
3.1 Interface: định nghĩa "shape" object
Interface = cách chính của TS để define object type:
interface User {
id: number
name: string
email: string
age?: number // Optional
}
const user: User = {
id: 1,
name: "Hoàng",
email: "h@example.com",
age: 25
}
// age optional, có thể bỏ
const user2: User = {
id: 2,
name: "Linh",
email: "l@example.com"
}🎯 Interface 接口演示
interface User {
id: number
name: string
email: string
age: number
}const user: User = {
id: 1,
name: "张三",
email: "zhangsan@example.com",
age: 25
} // ✅ 类型完全匹配const user: User = {
id: 1,
name: "张三",
email: "zhangsan@example.com",
age: "25" // ❌ 错误:age 应该是 number,不是 string
}Interface khác
// Readonly
interface User {
readonly id: number // Không sửa được sau tạo
name: string
}
const user: User = { id: 1, name: "Hoàng" }
user.id = 2 // ❌ Error
user.name = "Linh" // ✅
// Function type
interface User {
name: string
greet: () => string
}
// Extends
interface Admin extends User {
permissions: string[]
}3.2 Type Alias
Ngoài interface, dùng type:
type User = {
id: number
name: string
}
// Union type
type Status = "pending" | "success" | "error"
const status: Status = "success" // ✅
// Intersection type
type User = { id: number; name: string }
type Timestamp = { createdAt: Date; updatedAt: Date }
type UserWithTimestamp = User & TimestampInterface vs Type:
| Feature | interface | type |
|---|---|---|
| Extend | extends | & intersection |
| Duplicate | Auto merge | Error |
| Use | Object shape, class | Union, intersection, basic alias |
4. Function type
4.1 Param + return type
function add(a: number, b: number): number {
return a + b
}
// Arrow function
const multiply = (a: number, b: number): number => a * b
// No return
function log(message: string): void {
console.log(message)
}
// Multiple return type (union)
function parseInput(input: string): number | string {
const num = parseFloat(input)
return isNaN(num) ? input : num
}4.2 Optional + default param
// Optional
function greet(name: string, title?: string): string {
return title ? `${title} ${name}` : name
}
// Default
function greet2(name: string, title: string = "friend"): string {
return `${title} ${name}`
}4.3 Function type as param
function calculate(
a: number,
b: number,
operation: (x: number, y: number) => number
): number {
return operation(a, b)
}
calculate(10, 5, (x, y) => x + y) // 15
// Clearer: define type trước
type Operation = (x: number, y: number) => number5. Generic
5.1 Basic
Generic = define function/interface/class không pre-specify type, lúc use mới specify:
// T = type variable
function identity<T>(arg: T): T {
return arg
}
const num1 = identity<number>(42) // type number
const str1 = identity<string>("hello") // type string
// Auto infer
const num2 = identity(42) // infer number
const str2 = identity("hello") // infer string🔄 泛型 (Generics) 演示
// T 是类型变量,使用时才会确定具体类型
function identity<T>(arg: T): T {
return arg
}
// 泛型数组反转
function reverseArray<T>(arr: T[]): T[] {
return [...arr].reverse()
}📝 泛型使用示例
const nums = [1, 2, 3, 4, 5]
const reversed = reverseArray<number>(nums)
// 结果: [5, 4, 3, 2, 1]
// 类型: number[]const strs = ["a", "b", "c"]
const reversed = reverseArray<string>(strs)
// 结果: ["c", "b", "a"]
// 类型: string[]5.2 Generic constraint
interface HasLength {
length: number
}
function logLength<T extends HasLength>(arg: T): void {
console.log(arg.length)
}
logLength("hello") // ✅
logLength([1, 2, 3]) // ✅
logLength(42) // ❌5.3 Generic interface + class
interface Box<T> {
value: T
getValue(): T
}
const numberBox: Box<number> = {
value: 42,
getValue: () => 42
}
// Generic class
class Storage<T> {
private items: T[] = []
add(item: T): void { this.items.push(item) }
get(index: number): T { return this.items[index] }
}
const numberStorage = new Storage<number>()
numberStorage.add(1)
// numberStorage.add("string") // ❌6. Type inference + tips
6.1 Type inference
const name = "Hoàng" // infer string
const numbers = [1, 2, 3] // infer number[]
const mixed = [1, "hello", true] // infer (number | string | boolean)[]
function add(a: number, b: number) {
return a + b // infer return number
}🔮 类型推断演示
什么是类型推断?
TypeScript 很聪明,它能根据你写的代码自动推断出变量的类型,不需要每次都手动标注。
选择一个示例看看类型推断是如何工作的:
let name = "张三"📚 最佳实践
- 变量初始化时有明确的值
- 函数返回值可以明显推断
- 简单的字面量赋值
- 函数参数(必须)
- 对象或数组的复杂结构
- 无法从初始值推断类型
- 需要明确的类型约束
🔄 类型推断 vs 显式注解
function add(a: number, b: number) {
return a + b // 推断为 number
}function add(a: number, b: number): number {
return a + b
}const user = {
name: "张三",
age: 25,
email: "test@example.com"
} // 类型自动推断interface User {
name: string
age: number
email: string
}
const user: User = { ... }6.2 Khi nào dùng annotation explicit
Dùng inference:
- Simple literal assignment
- Function return value clear
Dùng annotation explicit:
- Function param (bắt buộc)
- Object property type unclear
- Function return type phức tạp
- Public API
6.3 Type guard
Check type lúc runtime:
// typeof
function processValue(value: string | number) {
if (typeof value === "string") {
console.log(value.toUpperCase()) // TS biết string
} else {
console.log(value * 2) // TS biết number
}
}
// instanceof
function makeSound(animal: Dog | Cat) {
if (animal instanceof Dog) animal.bark()
else animal.meow()
}
// Custom type guard
function isUser(value: any): value is User {
return typeof value === "object" &&
value !== null &&
typeof value.name === "string"
}6.4 Utility types
interface User {
id: number
name: string
email: string
}
type PartialUser = Partial<User> // Mọi prop optional
type RequiredUser = Required<PartialUser> // Mọi prop required
type UserBasic = Pick<User, "id" | "name"> // Chỉ id + name
type UserNoEmail = Omit<User, "email"> // Bỏ email
type UserRoles = Record<string, boolean> // { [key: string]: boolean }7. TS trong vibecoding
7.1 Để AI gen type-safe code
Tệ:
Viết feature quản userTốt:
Viết feature quản user, dùng TypeScript.
Data structure:
interface User {
id: number
name: string
email: string
age: number
}
Implement:
1. Get user list: return User[]
2. Create user: input Partial<User>, return User
3. Update user: input id + Partial<User>, return User
4. Delete user: input id, return void
Đảm bảo mọi function có type annotation đầy đủ.7.2 Đọc TS error
| Error | Nghĩa | Giải |
|---|---|---|
Type 'X' is not assignable to type 'Y' | X không gán được cho Y | Check type match |
Property 'X' does not exist on type 'Y' | Y không có prop X | Check spelling hoặc define prop |
Argument of type 'X' is not assignable to parameter of type 'Y' | Param type không match | Check param type lúc call |
Type 'X' is missing the following properties | X thiếu prop của Y | Add prop thiếu |
7.3 Migrate gradual
- Rename
.js→.ts - Fix obvious type error
- Add type definition dần
- Enable strict mode:json
{ "compilerOptions": { "strict": true } }
8. Code bạn đọc được
: string→ string annotation: number[]→ number arrayinterface User→ object typetype User =→ type alias<T>→ genericextends→ interface inherit / generic constraint?→ optionalreadonly→ readonly|→ union&→ intersection
Hỏi AI thế nào
- "Function này type annotation thế nào? Param X, return Y"
- "Define interface cho data structure này: ..."
- "TS error này nghĩa gì? Fix thế nào?"
- "Generic function này thêm constraint thế nào, đảm bảo T có prop?"
2026 cho VN dev
- TypeScript 5.7+: stable, default cho mọi project mới
- tsconfig strict: bật
strict: true,noUncheckedIndexedAccess,noImplicitOverride - No
any: dùngunknown, có type guard - Runtime validation: Zod (mainstream), Valibot (smaller), Effect Schema
- Type-safe ORM: Prisma, Drizzle, Kysely
- End-to-end type safety: tRPC, Hono RPC, GraphQL Codegen
- VN dev: từ project mới phải dùng TS, JS thuần out-of-date cho production