Cả hai đều mô tả shape của dữ liệu và thường có thể thay thế cho nhau, nhưng chúng có những khả năng khác nhau.
interface User { name: string; age: number; }
type User2 = { name: string; age: number; };
Những gì type làm được mà interface không làm được
type ID = string | number; // union
type Pair = [number, number]; // tuple
type Name = User["name"]; // indexed/mapped/conditional type
type Nullable<T> = T | null; // bọc bất kỳ type nào
type là một alias tổng quát cho bất kỳ type nào — kiểu nguyên thủy, union, tuple, mapped type. interface chỉ mô tả shape của object/function.
Những gì interface làm được mà type không làm được
interface Box { width: number; }
interface Box { height: number; } // declaration merging — cả hai gộp thành một
// Box bây giờ có cả width VÀ height
Interface hỗ trợ declaration merging (nhiều khai báo gộp lại với nhau) và là cách idiomatic để extend/augment, bao gồm cả việc augment các type của thư viện bên thứ ba.
Cú pháp mở rộng (extension)
interface Admin extends User { role: string; } // interface
type Admin2 = User & { role: string }; // type dùng intersection
Nên dùng cái nào
Một quy ước phổ biến: dùng interface cho shape của object và các public API (thông báo lỗi tốt hơn, có thể extend, có thể merge), và dùng type khi bạn cần union, tuple, hoặc các phép toán type khác. Hãy chọn một cái làm mặc định để nhất quán — nhiều team mặc định dùng interface cho object và chỉ dùng đến type khi cần thêm sức mạnh của nó.
