TypeScript không tự động làm ứng dụng an toàn chỉ vì file có đuôi .ts. Nếu dự án dùng nhiều any, bỏ qua null và ép kiểu tùy tiện, nhiều lỗi vẫn chỉ xuất hiện khi người dùng thao tác. strict biến trình biên dịch thành một lớp kiểm tra thiết kế hữu ích hơn.
Bật strict mode có thể làm một dự án cũ xuất hiện hàng trăm lỗi. Điều đó không có nghĩa code vừa hỏng; compiler đang chỉ ra những giả định vốn đã tồn tại nhưng chưa được kiểm chứng.
strict thực sự bật những gì?
Trong tsconfig.json, cấu hình nền tảng rất ngắn:
{
"compilerOptions": {
"strict": true,
"noEmit": true
}
}
strict bật một họ kiểm tra như strictNullChecks, noImplicitAny, strictFunctionTypes, strictPropertyInitialization và useUnknownInCatchVariables. Các phiên bản TypeScript tương lai có thể bổ sung kiểm tra mới vào nhóm này, vì vậy cần chạy type-check trong CI khi nâng cấp.
strictNullChecks loại bỏ giả định nguy hiểm
const user = users.find((item) => item.id === selectedId);
// Error under strictNullChecks: user may be undefined.
console.log(user.name);
Cách sửa không phải luôn thêm dấu !. Hãy thể hiện đúng nghiệp vụ:
if (!user) {
throw new Error('Selected user was not found');
}
console.log(user.name);
Nếu không tìm thấy là tình huống bình thường, hàm nên trả về User | undefined và caller phải xử lý. Nếu đó là invariant, hãy kiểm tra một lần ở biên hệ thống rồi dùng kiểu hẹp hơn bên trong.
Không thay any bằng ép kiểu
any tắt kiểm tra kiểu và có xu hướng lan truyền. Với dữ liệu từ API, local storage hoặc message queue, điểm bắt đầu trung thực hơn là unknown:
function parseProfile(input: unknown): Profile {
if (!isProfile(input)) {
throw new Error('Invalid profile payload');
}
return input;
}
Type guard hoặc thư viện schema validation giúp thu hẹp unknown sau khi đã kiểm tra runtime. Kiểu TypeScript bị xóa khi build nên không thể thay thế validation ở ranh giới dữ liệu.
Xử lý lỗi trong catch đúng cách
JavaScript cho phép ném bất kỳ giá trị nào, không chỉ Error. Vì vậy strict mode xem biến trong catch là unknown:
try {
await saveOrder();
} catch (error: unknown) {
const message = error instanceof Error
? error.message
: 'Unknown error';
reportFailure(message);
}
Đoạn kiểm tra nhỏ này tránh việc truy cập error.message trên một giá trị không có thuộc tính đó.
Dùng union phân biệt thay cho nhiều boolean
type LoadState =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'success'; data: User[] }
| { status: 'error'; message: string };
So với ba boolean isLoading, hasError, hasData, discriminated union loại bỏ các trạng thái mâu thuẫn. Một switch theo status cũng giúp compiler thu hẹp đúng dữ liệu có sẵn.
Kiểm tra đầy đủ bằng never
function renderState(state: LoadState): string {
switch (state.status) {
case 'idle': return 'Ready';
case 'loading': return 'Loading';
case 'success': return `${state.data.length} users`;
case 'error': return state.message;
default: return assertNever(state);
}
}
function assertNever(value: never): never {
throw new Error(`Unhandled state: ${JSON.stringify(value)}`);
}
Khi thêm một trạng thái mới mà quên xử lý, type-check sẽ báo lỗi tại assertNever.
Dùng satisfies để kiểm tra mà vẫn giữ inference
type RouteName = 'home' | 'account';
const routes = {
home: '/',
account: '/account',
} satisfies Record<RouteName, string>;
satisfies xác minh object phù hợp với contract nhưng vẫn giữ kiểu cụ thể của biểu thức. Nó hữu ích cho config, route map và dictionary cần đủ key.
Hạn chế non-null assertion và type assertion
value! và value as SomeType nói với compiler rằng lập trình viên biết rõ hơn, nhưng không tạo kiểm tra runtime. Chúng phù hợp tại một số ranh giới framework đã được đảm bảo, song không nên là cách mặc định để “dọn” lỗi strict.
- Ưu tiên kiểm tra điều kiện hoặc optional chaining.
- Dùng assertion function khi một invariant được kiểm tra tập trung.
- Validate dữ liệu ngoài hệ thống trước khi cast.
- Không dùng
as unknown as Tđể vượt contract.
Lộ trình bật strict cho dự án cũ
- Tạo lệnh type-check riêng và đưa vào CI.
- Bật
strictNullCheckstrước nếu dự án có nhiều lỗi null. - Sửa từ module biên: API client, parser, shared types.
- Thay
anybằngunknowntại đầu vào không tin cậy. - Dùng danh sách lỗi làm backlog, không thêm lỗi mới.
- Bật toàn bộ
strict, sau đó cân nhắcnoUncheckedIndexedAccessvàexactOptionalPropertyTypestheo nhu cầu.
Không nên tắt strict toàn dự án chỉ vì một thư viện có type chưa tốt. Hãy cô lập adapter, bổ sung type declaration hoặc dùng một ngoại lệ nhỏ có ghi chú.
Checklist review code TypeScript
- Dữ liệu bên ngoài bắt đầu từ
unknownvà được validate. - Không truy cập giá trị có thể null/undefined khi chưa kiểm tra.
- Union thể hiện trạng thái hợp lệ thay cho tổ hợp boolean.
- Assertion có lý do rõ ràng và phạm vi nhỏ.
- Type-check chạy trong CI, tách khỏi bundler nếu cần.
- Nâng TypeScript có bước đọc release notes và xử lý lỗi strict mới.




Chưa có bình luận. Hãy là người đầu tiên chia sẻ ý kiến.