Structural typing, inference, unions và narrowing
TypeScript kiểm tra source rồi erase types; JSON/network/localStorage vẫn là unknown cho đến khi runtime validation chứng minh shape.
unknown thành domain type qua schema/guard có evidence, không dùng as để che failure.1. Structural model và inference
Compatibility dựa trên members, không nominal identity. Excess-property checks mạnh hơn với fresh literals nhưng không biến TypeScript thành exact object types. Inference giúp giảm annotation nhưng cần kiểm tra widening, contextual typing và public API stability.
Mutable variance và callback parameter compatibility có soundness trade-off; strict mode làm các khoảng mơ hồ lộ sớm hơn.
2. Top/bottom types
| Type | Ý nghĩa | Policy |
|---|---|---|
unknown | Giá trị chưa biết, phải narrow trước use | Default cho external input |
any | Tắt checker và lan truyền unsafety | Localize, document reason, lint |
never | Không thể xảy ra/exhaustiveness | Dùng ở assertNever hoặc impossible branch |
void | Giá trị return không hữu ích | Không nhầm với async cancellation |
3. Unions và control-flow narrowing
Discriminated union model state machine; typeof, in, instanceof, equality checks và custom predicates narrow theo control flow. Exhaustive switch với never bắt missing case khi union phát triển.
type Result = {kind: "ok"; value: string} | {kind: "error"; message: string};
function render(r: Result) {
switch (r.kind) {
case "ok": return r.value;
case "error": return r.message;
default: return assertNever(r);
}
}
4. Nullability và runtime validation
strictNullChecks tách null/undefined; optional property khác property union undefined khi bật exactOptionalPropertyTypes. Non-null assertion chỉ xóa checker warning, không tạo runtime proof. Validate external data bằng schema/guard rồi map sang domain object.
- Không cast API response trực tiếp thành interface.
- Giữ validation error machine-readable và gắn input boundary.
- Type guard phải kiểm tra đủ invariant mà downstream cần, không chỉ một field.