Lưu ý: Trang này đã cũ. Danh sách đầy đủ được duy trì tại https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler
Tổng quan
Trình biên dịch đóng có thể sử dụng thông tin loại dữ liệu về các biến JavaScript để cung cấp tính năng cảnh báo và tối ưu hoá nâng cao. Tuy nhiên, JavaScript không có cách nào để khai báo loại dữ liệu.
Vì JavaScript không có cú pháp để khai báo loại biến, nên bạn phải sử dụng các chú thích trong mã để chỉ định loại dữ liệu.
Ngôn ngữ của Trình biên dịch khép kín bắt nguồn từ các chú thích mà công cụ tạo tài liệu JSDoc sử dụng, mặc dù ngôn ngữ này đã được phân biệt. Giờ đây, trang này bao gồm một số chú thích mà JSDoc không hỗ trợ và ngược lại. Tài liệu này mô tả tập hợp các chú thích và biểu thức loại mà Trình biên dịch đóng đã hiểu.
Thẻ JSDoc
Trình biên dịch đóng cửa tìm kiếm thông tin loại trong các thẻ JSDoc. Sử dụng các thẻ JSDoc được mô tả trong bảng tham chiếu dưới đây để giúp trình biên dịch tối ưu hoá mã của bạn và kiểm tra mã đó để tìm các lỗi loại và các lỗi khác có thể xảy ra.
Bảng này chỉ bao gồm các thẻ ảnh hưởng đến hành vi của Trình biên dịch đóng. Để biết thông tin về các thẻ JSDoc khác, hãy xem tài liệu về Bộ công cụ JSDoc.
Thẻ | Mô tả |
---|---|
@abstract
|
Đánh dấu một phương thức là trừu tượng. Tương tự như việc đặt một phương thức thành
Trình biên dịch tạo một cảnh báo nếu một phương thức được đánh dấu bằng /** @abstract */ foo.MyClass.prototype.abstractMethod = function() {}; |
@const
|
Đánh dấu một biến là chỉ có thể đọc. Trình biên dịch có thể cùng dòng biến Phần khai báo loại là không bắt buộc.
Trình biên dịch tạo một cảnh báo nếu một biến được đánh dấu bằng /** @const */ var MY_BEER = 'stout'; /** * My namespace's favorite kind of beer. * @const {string} */ mynamespace.MY_BEER = 'stout'; /** @const */ MyClass.MY_BEER = 'stout'; |
@constructor
|
Đánh dấu một hàm là hàm khởi tạo.
Trình biên dịch yêu cầu chú thích Ví dụ: /** * A rectangle. * @constructor */ function GM_Rect() { ... } |
@define
|
Cho biết một hằng số có thể được trình biên dịch ghi đè tại thời điểm biên dịch.
Với ví dụ ở bên trái, bạn có thể chuyển cờ
-- lâu='ENABLE_DEBUG=false'
vào trình biên dịch để thay đổi giá trị của
ENABLE_DEBUG thành false.
Loại của một hằng số đã xác định có thể là số, chuỗi hoặc boolean.
Chỉ cho phép định nghĩa trong phạm vi toàn cầu.
Ví dụ: /** @define {boolean} */ var ENABLE_DEBUG = true; /** @define {boolean} */ goog.userAgent.ASSUME_IE = false; |
@deprecated
|
Đánh dấu một hàm, phương thức hoặc thuộc tính để sử dụng sẽ tạo ra cảnh báo của trình biên dịch cho biết rằng hàm đó không còn được sử dụng nữa. Ví dụ: /** * Determines whether a node is a field. * @return {boolean} True if the contents of * the element are editable, but the element * itself is not. * @deprecated Use isField(). */ BN_EditUtil.isTopEditableField = function(node) { ... }; |
@dict
|
Ví dụ: /** * @constructor * @dict */ function Foo() {} var obj1 = new Foo(); obj1['x'] = 123; obj1.x = 234; // warning var obj2 = /** @dict */ { 'x': 321 }; obj2.x = 123; // warning |
@enum
|
Chỉ định loại enum. Enum là một đối tượng có các thuộc tính cấu thành một tập hợp các hằng số có liên quan. Theo sau thẻ Nhãn loại của một enum áp dụng cho từng thuộc tính của enum. Chẳng hạn nếu một enum có loại Ví dụ: /** * Enum for tri-state values. * @enum {number} */ project.TriState = { TRUE: 1, FALSE: -1, MAYBE: 0 }; |
@export
|
Đã cung cấp mã này /** @export */ foo.MyPublicClass.prototype.myPublicMethod = function() { // ... };
khi trình biên dịch được chạy bằng cờ goog.exportProperty(foo.MyPublicClass.prototype, 'myPublicMethod', foo.MyPublicClass.prototype.myPublicMethod); Thao tác này sẽ xuất các ký hiệu sang mã chưa biên dịch. Bạn có thể viết
/** * @export * @type {SomeType} */ Mã sử dụng chú thích
|
@extends
|
Đánh dấu một lớp hoặc giao diện là kế thừa từ một lớp khác. Lớp được đánh dấu bằng
Lưu ý:
Để xem ví dụ về cách triển khai tính kế thừa, hãy xem hàm Thư viện đóng Ví dụ: /** * Immutable empty node list. * @constructor * @extends {goog.ds.BasicNodeList} */ goog.ds.EmptyNodeList = function() { ... }; |
@final
|
Cho biết rằng lớp này không được phép mở rộng. Đối với các phương thức, hãy cho biết rằng không có lớp con nào được phép ghi đè phương thức đó. Ví dụ: /** * A class that cannot be extended. * @final * @constructor */ sloth.MyFinalClass = function() { ... } /** * A method that cannot be overridden. * @final */ sloth.MyFinalClass.prototype.method = function() { ... }; |
@implements
|
Được dùng với
Trình biên dịch tạo một cảnh báo nếu bạn gắn thẻ một hàm dựng
bằng Ví dụ: /** * A shape. * @interface */ function Shape() {}; Shape.prototype.draw = function() {}; /** * @constructor * @implements {Shape} */ function Square() {}; Square.prototype.draw = function() { ... }; |
@implicitCast
|
Chú thích này chỉ có thể xuất hiện trong nội dung khai báo về tài sản bên ngoài.
Thuộc tính có một loại đã khai báo, nhưng bạn có thể chỉ định bất kỳ loại nào cho loại đó mà không có cảnh báo. Khi truy cập vào thuộc tính, bạn sẽ nhận lại một giá trị của loại đã khai báo. Ví dụ:
/** * @type {string} * @implicitCast */ Element.prototype.innerHTML; |
@inheritDoc
|
Cho biết rằng một phương thức hoặc thuộc tính của một lớp con
đã cố ý ẩn một phương thức hoặc thuộc tính của lớp cao cấp và có
chính xác cùng một tài liệu. Lưu ý rằng thẻ Ví dụ: /** @inheritDoc */ project.SubClass.prototype.toString = function() { ... }; |
@interface
|
Đánh dấu một hàm là giao diện. Giao diện chỉ định các thành viên
bắt buộc của một loại. Mọi lớp triển khai giao diện đều phải triển khai tất cả các phương thức và thuộc tính được xác định trên nguyên mẫu của giao diện. Xem
Trình biên dịch xác minh rằng giao diện không được tạo bản sao. Nếu bạn sử dụng từ khóa Ví dụ: /** * A shape. * @interface */ function Shape() {}; Shape.prototype.draw = function() {}; /** * A polygon. * @interface * @extends {Shape} */ function Polygon() {}; Polygon.prototype.getSides = function() {}; |
@lends
|
Cho biết rằng các khoá của một đối tượng cố định phải được xem là thuộc tính của một số đối tượng khác. Chú thích này chỉ được xuất hiện trên giá trị cố định của đối tượng.
Hãy lưu ý rằng tên trong dấu ngoặc nhọn không phải là tên loại như trong các chú thích khác. Đó là tên đối tượng. Công cụ này đặt tên cho đối tượng mà các thuộc tính cho mượn.
Ví dụ: Tài liệu về Bộ công cụ JSDoc có thêm thông tin về chú thích này. Ví dụ: goog.object.extend( Button.prototype, /** @lends {Button.prototype} */ ({ isButton: function() { return true; } })); |
@license hoặc @preserve
|
Yêu cầu trình biên dịch chèn nhận xét liên quan trước mã đã biên dịch cho tệp được đánh dấu. Chú thích này cho phép các thông báo quan trọng (chẳng hạn như giấy phép pháp lý hoặc văn bản bản quyền) không bị thay đổi. Ngắt dòng được giữ nguyên. Ví dụ: /** * @preserve Copyright 2009 SomeThirdParty. * Here is the full license text and copyright * notice for this file. Note that the notice can span several * lines and is only terminated by the closing star and slash: */ |
@nocollapse
|
Mô tả một thuộc tính mà trình biên dịch không nên thu gọn thành một biến. Mục đích sử dụng chính của Ví dụ: /** * A namespace. * @const */ var foo = {}; /** * @nocollapse */ foo.bar = 42; window['foobar'] = foo.bar; |
@nosideeffects
|
Cho biết rằng lệnh gọi đến hàm bên ngoài đã khai báo không có tác dụng phụ.
Chú thích này cho phép trình biên dịch xoá các lệnh gọi đến hàm nếu giá trị trả về không được sử dụng. Chỉ được sử dụng chú thích trong Ví dụ: /** @nosideeffects */ function noSideEffectsFn1() {} /** @nosideeffects */ var noSideEffectsFn2 = function() {}; /** @nosideeffects */ a.prototype.noSideEffectsFn3 = function() {}; |
@override
|
Cho biết rằng một phương thức hoặc thuộc tính của một lớp con sẽ cố ý ẩn một phương thức hoặc thuộc tính của lớp cao cấp. Nếu không có chú thích nào khác được đưa vào, phương thức hoặc thuộc tính đó sẽ tự động kế thừa các chú thích từ lớp cao cấp. Ví dụ: /** * @return {string} Human-readable representation of * project.SubClass. * @override */ project.SubClass.prototype.toString = function() { ... }; |
@package
|
Đánh dấu một thành viên hoặc tài sản là gói riêng tư. Chỉ mã trong cùng thư mục mới có thể truy cập vào tên được đánh dấu là
Các hàm dựng công khai có thể có các thuộc tính Ví dụ: /** * Returns the window object the foreign document resides in. * * @return {Object} The window object of the peer. * @package */ goog.net.xpc.CrossPageChannel.prototype.getPeerWindowObject = function() { // ... }; |
@param
|
Được dùng với các định nghĩa phương thức, hàm và hàm khởi tạo để chỉ định
các loại đối số của hàm. Các thẻ
Thẻ
Ngoài ra, bạn có thể chú thích các loại tham số cùng dòng
(xem ví dụ về hàm Ví dụ: /** * Queries a Baz for items. * @param {number} groupNum Subgroup id to query. * @param {string|number|null} term An itemName, * or itemId, or null to search everything. */ goog.Baz.prototype.query = function(groupNum, term) { ... }; function foo(/** number */ a, /** number */ b) { return a - b + 1; }Đối với các tham số là mẫu huỷ cấu trúc, bạn có thể sử dụng bất kỳ tên nào là giá trị nhận dạng JS hợp lệ, sau chú thích kiểu. /** * @param {{name: string, age: number}} person */ function logPerson({name, age}) { console.log(`${name} is ${age} years old`); } |
@private
|
Đánh dấu một thành viên là riêng tư. Chỉ mã trong cùng một tệp mới có thể truy cập vào các biến và hàm toàn cục được đánh dấu là
Bạn cũng có thể truy cập vào các thuộc tính tĩnh công khai của các hàm khởi tạo có nhãn Ví dụ: /** * Handlers that are listening to this logger. * @private {Array<Function>} */ this.handlers_ = []; |
@protected
|
Cho biết rằng một thành viên hoặc tài sản được bảo vệ.
Một tài sản được đánh dấu là
Ví dụ: /** * Sets the component's root element to the given element. * Considered protected and final. * @param {Element} element Root element for the component. * @protected */ goog.ui.Component.prototype.setElementInternal = function(element) { // ... }; |
@record
|
Đánh dấu một hàm là giao diện cấu trúc. Giao diện cấu trúc tương tự như Ví dụ: /** * Anything with a draw() method. * @record */ function Drawable() {}; Drawable.prototype.draw = function() {}; /** * A polygon. * @param {!Drawable} x */ function render(x) { x.draw(); }; var o = { draw() { /* ... */ } }; render(o); |
@return
|
Chỉ định loại dữ liệu trả về cho các phương thức định nghĩa hàm và phương thức.
Thẻ
Ngoài ra, bạn có thể chú thích loại dữ liệu trả về nội tuyến (xem ví dụ về hàm
Nếu một hàm không ở ngoài bộ nhớ ngoài không có giá trị trả về, bạn có thể bỏ qua thẻ Ví dụ: /** * Returns the ID of the last item. * @return {string} The hex ID. */ goog.Baz.prototype.getLastId = function() { ... return id; }; function /** number */ foo(x) { return x - 1; } |
@struct
|
Ví dụ: /** * @constructor * @struct */ function Foo(x) { this.x = x; } var obj1 = new Foo(123); var someVar = obj1.x; // OK obj1.x = "qwerty"; // OK obj1['x'] = "asdf"; // warning obj1.y = 5; // warning var obj2 = /** @struct */ { x: 321 }; obj2['x'] = 123; // warning |
@template
|
Xem mục Loại chung. Ví dụ: /** * @param {T} t * @constructor * @template T */ Container = function(t) { ... }; |
@this
|
Chỉ định loại đối tượng mà từ khoá
Để ngăn cảnh báo của trình biên dịch, bạn phải sử dụng chú thích Ví dụ: chat.RosterWidget.extern('getRosterElement', /** * Returns the roster widget element. * @this {Widget} * @return {Element} */ function() { return this.getComponent().getElement(); }); |
@throws
|
Dùng để ghi nhận các trường hợp ngoại lệ do một hàm gửi. Trình kiểm tra loại hiện không sử dụng thông tin này. Lệnh này chỉ được dùng để xác định xem một hàm được khai báo trong tệp externs có tác dụng phụ hay không. Ví dụ: /** * @throws {DOMException} */ DOMApplicationCache.prototype.swapCache = function() { ... }; |
@type
|
Xác định loại biến, thuộc tính hoặc biểu thức. Theo sau thẻ Khi khai báo một biến hoặc tham số hàm, bạn có thể viết chú thích kiểu cùng dòng bỏ qua Ví dụ: /** * The message hex ID. * @type {string} */ var hexId = hexId; var /** string */ name = 'Jamie'; function useSomething(/** (string|number|!Object) */ something) { ... } |
@typedef
|
Khai báo một biệt hiệu cho một loại phức tạp hơn. Hiện tại, typedef chỉ có thể được xác định ở cấp cao nhất, không phải trong hàm. Chúng tôi đã khắc phục hạn chế này trong suy luận kiểu dữ liệu mới. Ví dụ: /** @typedef {(string|number)} */ goog.NumberLike; /** @param {goog.NumberLike} x A number or a string. */ goog.readNumber = function(x) { ... } |
@unrestricted
|
Cho biết lớp không phải là loại Ví dụ: /** * @constructor * @unrestricted */ function Foo(x) { this.x = x; } var obj1 = new Foo(123); var someVar = obj1.x; // OK obj1.x = "qwerty"; // OK obj1['x'] = "asdf"; // OK obj1.y = 5; // OK |
Loại biểu thức
Bạn có thể chỉ định kiểu dữ liệu cho mọi tham số của biến, thuộc tính, biểu thức hoặc hàm bằng biểu thức kiểu. Biểu thức loại bao gồm dấu ngoặc nhọn ("{ }") chứa một số tổ hợp toán tử loại được mô tả bên dưới.
Sử dụng biểu thức loại với thẻ @param
để khai báo loại tham số của hàm. Sử dụng biểu thức loại với thẻ @type
để khai báo loại biến, thuộc tính hoặc biểu thức.
Bạn chỉ định càng nhiều loại mã trong mã, thì trình biên dịch càng có thể thực hiện quá trình tối ưu hoá và càng có nhiều lỗi.
Trình biên dịch sử dụng các chú thích này để kiểm tra loại chương trình của bạn.
Xin lưu ý rằng Trình biên dịch đóng không đưa ra bất kỳ lời hứa nào có thể xác định loại của mọi biểu thức trong chương trình. Bạn sẽ nỗ lực hết sức bằng cách xem xét cách sử dụng biến và chú thích trong các loại kèm theo nội dung khai báo. Sau đó, Google sẽ sử dụng một số thuật toán suy luận loại để tìm ra loại biểu thức càng nhiều càng tốt. Một số thuật toán trong số này rất đơn giản ("nếu x là số và chúng tôi thấy y = x;
, thì y là số"). Một số gián tiếp hơn ("nếu tham số đầu tiên của f được ghi lại dưới dạng lệnh gọi lại phải nhận một số) và chúng ta thấy f(function(x) { /** ... */ });
, thì x phải là một số").
Tên nhà cung cấp dịch vụ | Ví dụ về cú pháp | Mô tả |
---|---|---|
Nhập tên |
{boolean} {Window} {goog.ui.Menu}
|
Chỉ định tên của một loại. |
Loại ứng dụng |
{Array<string>} Một mảng chuỗi.
|
Tham số hoá một kiểu có một tập hợp các đối số kiểu. Tương tự như các thành phần chung của Java. |
Loại kết hợp |
{(number|boolean)} Một số hoặc boolean. Lưu ý dấu ngoặc đơn là bắt buộc. |
Cho biết rằng một giá trị có thể có loại A HOẶC loại B. |
Loại bản ghi |
{{myNum: number, myObject}}
Một loại ẩn danh có cả thuộc tính có tên myNum
có giá trị thuộc loại number và thuộc tính có tên myObject có giá trị thuộc loại bất kỳ.
|
Cho biết giá trị có các thành phần đã chỉ định kèm theo giá trị của các loại đã chỉ định. Dấu ngoặc nhọn là một phần của cú pháp loại. Ví dụ: để mô tả |
Loại có thể rỗng |
{?number} Một số hoặc null .
|
Cho biết giá trị thuộc loại A hoặc Theo mặc định, tất cả các loại đối tượng đều có thể rỗng cho dù chúng được khai báo bằng toán tử Nullable. Loại đối tượng được xác định là bất kỳ giá trị nào, ngoại trừ hàm, chuỗi, số hoặc boolean. Để loại đối tượng không thể nhận giá trị rỗng, hãy sử dụng toán tử Non-nullable. |
Loại không rỗng |
{!Object} Một đối tượng, nhưng không bao giờ có giá trị null .
|
Cho biết giá trị thuộc loại A chứ không phải giá trị rỗng. Theo mặc định, các hàm và mọi loại giá trị (boolean, số và chuỗi) không thể nhận giá trị rỗng cho dù các hàm đó có được khai báo hay không bằng toán tử không rỗng. Để đặt một giá trị hoặc loại hàm có thể có giá trị rỗng, hãy sử dụng toán tử Nullable. |
Loại hàm |
{function(string, boolean)} Một hàm nhận hai tham số (một chuỗi và một boolean) và có giá trị trả về không xác định. |
Chỉ định một hàm và các loại tham số của hàm. |
Loại dữ liệu trả về của hàm |
{function(): number} Hàm không nhận tham số và trả về số. |
Chỉ định loại giá trị trả về của một hàm. |
Loại hàm this |
{function(this:goog.ui.Menu, string)} Hàm nhận một tham số (một chuỗi) và thực thi trong ngữ cảnh của một goog.ui.Menu. |
Chỉ định loại giá trị của this trong hàm. |
Loại hàm new |
{function(new:goog.ui.Menu, string)} Hàm lấy một tham số (một chuỗi) và tạo một thực thể mới của goog.ui.Menu khi được gọi bằng từ khoá "new". |
Chỉ định loại hàm khởi tạo được tạo. |
Thông số biến |
{function(string, ...number): number} Hàm có một tham số (một chuỗi) và sau đó là một số tham số phải là số. |
Cho biết rằng loại hàm nhận số lượng thông số thay đổi và chỉ định một loại cho các thông số biến. |
Tham số biến (trong chú thích @param )
|
@param {...number} var_args Số lượng tham số có thể thay đổi đối với một hàm được chú thích. |
Cho biết rằng hàm được chú thích chấp nhận số lượng thông số thay đổi và chỉ định một loại cho các thông số của biến. |
Tham số không bắt buộc trong chú thích @param
|
@param {number=} opt_argument Thông số không bắt buộc thuộc loại number .
|
Cho biết rằng đối số được mô tả bằng chú thích
Nếu lệnh gọi phương thức bỏ qua một tham số không bắt buộc, đối số đó sẽ có
giá trị là /** * Some class, initialized with an optional value. * @param {Object=} opt_value Some value (optional). * @constructor */ function MyClass(opt_value) { /** * Some value. * @type {Object|undefined} */ this.myValue = opt_value; } |
Đối số tùy chọn trong một loại hàm |
{function(?string=, number=)} Một hàm nhận một chuỗi không bắt buộc và một số không bắt buộc làm đối số. |
Cho biết một đối số trong loại hàm là không bắt buộc. Bạn có thể bỏ qua một đối số không bắt buộc khỏi lệnh gọi hàm. Một đối số không bắt buộc không được đứng trước đối số không bắt buộc trong danh sách đối số. |
Loại TẤT CẢ | {*} |
Cho biết biến có thể nhận bất kỳ loại nào. |
Loại KHÔNG XÁC ĐỊNH | {?} |
Cho biết biến có thể nhận bất kỳ loại nào và trình biên dịch không nên kiểm tra bất kỳ cách sử dụng nào của biến đó. |
Truyền kiểu
Để truyền một giá trị đến một loại cụ thể, hãy sử dụng cú pháp này
/** @type {!MyType} */ (valueExpression)Bạn luôn phải đặt dấu ngoặc đơn xung quanh biểu thức.
Loại chung
Tương tự như Java, Trình biên dịch đóng hỗ trợ các loại, hàm và phương thức chung. Thành phần chung hoạt động trên các đối tượng thuộc nhiều loại trong khi vẫn duy trì sự an toàn cho loại thời gian biên dịch.
Bạn có thể sử dụng các thành phần chung để triển khai các bộ sưu tập tổng quát chứa tệp tham chiếu đến các đối tượng của một loại cụ thể, và các thuật toán tổng quát hoạt động trên các đối tượng của một loại cụ thể.
Khai báo loại chung
Bạn có thể tạo một loại chung bằng cách thêm chú thích @template
vào hàm khởi tạo của loại đó (cho lớp) hoặc khai báo giao diện (cho
giao diện). Ví dụ:
/** * @constructor * @template T */ Foo = function() { ... };
Chú thích @template T
cho biết rằng Foo
là một loại chung với một loại mẫu, T
.
Bạn có thể sử dụng loại mẫu T
làm loại trong phạm vi
định nghĩa Foo
. Ví dụ:
/** @return {T} */ Foo.prototype.get = function() { ... }; /** @param {T} t */ Foo.prototype.set = function(t) { ... };
Phương thức get
sẽ trả về một đối tượng thuộc loại T
và phương thức set
sẽ chỉ chấp nhận các đối tượng thuộc loại T
.
Tạo thực thể cho một loại chung
Khi sử dụng lại ví dụ trên, bạn có thể tạo một thực thể mẫu của Foo
theo một số cách sau:
/** @type {!Foo<string>} */ var foo = new Foo(); var foo = /** @type {!Foo<string>} */ (new Foo());
Cả hai câu lệnh hàm khởi tạo ở trên đều tạo một phiên bản Foo
có loại mẫu T
là string
. Trình biên dịch sẽ thực thi các lệnh gọi đến các phương thức của foo
và truy cập vào các thuộc tính của foo
, tuân theo loại mẫu. Ví dụ:
foo.set("hello"); // OK. foo.set(3); // Error - expected a string, found a number. var x = foo.get(); // x is a string.
Các thực thể cũng có thể được nhập hoàn toàn từ các đối số hàm dựng.
Hãy xem xét một loại chung khác, Bar
:
/** * @param {T} t * @constructor * @template T */ Bar = function(t) { ... }; var bar = new Bar("hello"); // bar is a Bar<string>
Loại đối số cho hàm khởi tạo Bar
được suy ra là string
, do đó, thực thể đã tạo bar
được suy ra là Bar<string>
.
Nhiều loại mẫu
Một thành phần chung có thể có số lượng mẫu bất kỳ. Lớp bản đồ sau có hai loại mẫu:
/** * @constructor * @template Key, Val */ MyMap = function() { ... };
Bạn phải chỉ định tất cả loại mẫu cho một loại chung trong cùng chú thích
@template
, như danh sách được phân tách bằng dấu phẩy. Thứ tự của tên loại mẫu là rất quan trọng vì chú thích kiểu mẫu sẽ sử dụng thứ tự để ghép nối các loại mẫu với các giá trị. Ví dụ:
/** @type {MyMap<string, number>} */ var map; // Key = string, Val = number.
Bất đẳng thức các loại chung
Trình biên dịch đóng đã thực thi thao tác nhập chung bất biến. Điều này có nghĩa là nếu một ngữ cảnh yêu cầu một loại Foo<X>
, thì bạn không thể chuyển một loại Foo<Y>
khi X
và Y
là các loại khác nhau, ngay cả khi một loại là loại phụ. Ví dụ:
/** * @constructor */ X = function() { ... }; /** * @extends {X} * @constructor */ Y = function() { ... }; /** @type {Foo<X>} */ var fooX; /** @type {Foo<Y>} */ var fooY; fooX = fooY; // Error fooY = fooX; // Error /** @param {Foo<Y>} fooY */ takesFooY = function(fooY) { ... }; takesFooY(fooY); // OK. takesFooY(fooX); // Error
Kế thừa các loại chung
Loại chung có thể được kế thừa và loại mẫu của bạn có thể được khắc phục hoặc truyền vào loại kế thừa. Dưới đây là ví dụ về một loại kế thừa sửa loại mẫu của loại siêu dữ liệu:
/** * @constructor * @template T */ A = function() { ... }; /** @param {T} t */ A.prototype.method = function(t) { ... }; /** * @constructor * @extends {A<string>} */ B = function() { ... };
Bằng cách mở rộng A<string>
, B
sẽ có một phương thức method
để nhận tham số thuộc loại string
.
Dưới đây là ví dụ về một loại kế thừa lan truyền loại mẫu của loại siêu dữ liệu:
/** * @constructor * @template U * @extends {A<U>} */ C = function() { ... };
Bằng cách mở rộng A<U>
, các bản sao mẫu của C
sẽ có một phương thức method
nhận tham số thuộc loại
U
.
Các giao diện có thể được triển khai và mở rộng theo cách tương tự nhau, nhưng một loại không thể triển khai cùng một giao diện nhiều lần với các loại mẫu khác nhau. Ví dụ:
/** * @interface * @template T */ Foo = function() {}; /** @return {T} */ Foo.prototype.get = function() {}; /** * @constructor * @implements {Foo<string>} * @implements {Foo<number>} */ FooImpl = function() { ... }; // Error - implements the same interface twice
Hàm và phương thức chung
Tương tự như các loại chung, các hàm và phương thức có thể được tạo chung bằng cách thêm chú thích @template
vào định nghĩa. Ví dụ:
/** * @param {T} a * @return {T} * @template T */ identity = function(a) { return a; }; /** @type {string} */ var msg = identity("hello") + identity("world"); // OK /** @type {number} */ var sum = identity(2) + identity(2); // OK /** @type {number} */ var sum = identity(2) + identity("2"); // Type mismatch