Trong TypeScript, toán tử ! (dấu chấm than/bang) là gì khi truy xuất một thành viên?
Khi xem mã nguồn của một quy tắc tslint, tôi đã bắt gặp câu lệnh sau:
if (node.parent!.kind === ts.SyntaxKind.ObjectLiteralExpression) {
return;
}
Hãy chú ý đến toán tử ! sau node.parent. Thật thú vị!
Lần đầu tiên tôi thử biên dịch tệp cục bộ với phiên bản TS hiện tại đang cài đặt của mình (1.5.3). Lỗi kết quả chỉ ra chính xác vị trí của dấu chấm than:
tsc --noImplicitAny memberAccessRule.ts
noPublicModifierRule.ts(57,24): error TS1005: ')' expected.
Tiếp theo, tôi đã nâng cấp lên TS mới nhất (2.1.6), và nó biên dịch mà không gặp vấn đề gì. Vì vậy có vẻ đây là một tính năng của TS 2.x. Nhưng, việc chuyển đổi đã bỏ qua dấu chấm than hoàn toàn, dẫn đến JS sau:
if (node.parent.kind === ts.SyntaxKind.ObjectLiteralExpression) {
return;
}
Kỹ năng Google của tôi cho đến nay đã thất bại.
Toán tử dấu chấm than của TS là gì, và nó hoạt động như thế nào?
Câu trả lời #1
Đó là toán tử khẳng định không-null. Nó là một cách để nói với trình biên dịch rằng "biểu thức này không thể là null hoặc undefined ở đây, vì vậy đừng than phiền về khả năng nó là null hoặc undefined." Đôi khi trình kiểm tra kiểu không thể tự đưa ra xác định đó.
Điều này được giải thích trong ghi chú phát hành TypeScript:
Một toán tử biểu thức hậu tố
!mới có thể được sử dụng để khẳng định rằng toán hạng của nó không phải là null và không phải là undefined trong những ngữ cảnh mà trình kiểm tra kiểu không thể xác định được điều đó. Cụ thể, phép toánx!tạo ra một giá trị có kiểu củaxvớinullvàundefinedbị loại trừ. Tương tự như các khẳng định kiểu ở dạng<T>xvàx as T, toán tử khẳng định không-null!đơn giản là bị loại bỏ trong mã JavaScript được tạo ra.
Tôi thấy việc sử dụng thuật ngữ "assert" hơi gây hiểu lầm trong phần giải thích đó. Nó là "assert" theo nghĩa nhà phát triển đang khẳng định điều đó, không phải theo nghĩa rằng một bài kiểm tra sẽ được thực hiện. Dòng cuối cùng thực sự chỉ ra rằng không có mã JavaScript nào được phát sinh.
Câu trả lời #2
Câu trả lời của Louis thật tuyệt, nhưng tôi nghĩ mình sẽ thử tóm tắt ngắn gọn:
Toán tử chấm than (bang) nói với trình biên dịch tạm thời nới lỏng ràng buộc "không null" mà nó có thể yêu cầu. Nó nói với trình biên dịch: "Là nhà phát triển, tôi biết rõ hơn bạn rằng biến này ngay bây giờ không thể là null".
Câu trả lời #3
Toán tử khẳng định không null
Với toán tử khẳng định không-null, chúng ta có thể cho trình biên dịch biết rõ ràng rằng một biểu thức có giá trị khác null hoặc undefined. Điều này có thể hữu ích khi trình biên dịch không thể suy ra loại một cách chắc chắn nhưng chúng ta có nhiều thông tin hơn so với trình biên dịch.
Ví dụ
Mã TS
function simpleExample(nullableArg: number | undefined | null) {
const normal: number = nullableArg;
// Compile err:
// Type 'number | null | undefined' is not assignable to type 'number'.
// Type 'undefined' is not assignable to type 'number'.(2322)
const operatorApplied: number = nullableArg!;
// compiles fine because we tell compiler that null | undefined are excluded
}
Mã JS đã biên dịch
Lưu ý rằng JS không biết khái niệm về toán tử xác nhận không null vì đây là một tính năng của TS
"use strict";
function simpleExample(nullableArg) {
const normal = nullableArg;
const operatorApplied = nullableArg;
}
Câu trả lời #4
Trả lời ngắn
Toán tử khẳng định không null (!) giúp trình biên dịch biết rằng tôi chắc chắn biến này không phải là null hoặc undefined.
let obj: { field: SampleType } | null | undefined;
... // some code
// the type of sampleVar is SampleType
let sampleVar = obj!.field; // we tell compiler we are sure obj is not null & not undefined so the type of sampleVar is SampleType
