참고: 오래된 페이지입니다. 전체 목록은 https://github.com/google/closure-compiler/wiki/Annotating-자바스크립트-for-the-Closure-Compiler에서 관리됩니다.
개요
클로저 컴파일러는 자바스크립트 변수에 관한 데이터 유형 정보를 사용하여 향상된 최적화와 경고를 제공할 수 있습니다. 그러나 자바스크립트에는 유형을 선언할 수 있는 방법이 없습니다.
자바스크립트에는 변수 유형을 선언하는 문법이 없으므로 코드의 주석을 사용하여 데이터 유형을 지정해야 합니다.
클로저 컴파일러의 유형 언어는 JSDoc 문서 생성 도구에서 사용한 주석에서 파생되었지만 그 이후 다양해졌습니다. 이제 JSDoc에서 지원하지 않는 주석이 몇 가지 포함되어 있으며 그 반대도 마찬가지입니다. 이 문서에서는 클로저 컴파일러에서 이해할 수 있는 주석 및 유형 표현식을 설명합니다.
JSDoc 태그
클로저 컴파일러는 JSDoc 태그에서 유형 정보를 찾습니다. 아래 참조 표에 설명된 JSDoc 태그를 사용하면 컴파일러가 코드를 최적화하고 유형 오류 및 기타 실수를 확인하는 데 도움이 됩니다.
이 표에는 클로저 컴파일러의 동작에 영향을 미치는 태그만 포함되어 있습니다. 다른 JSDoc 태그에 관한 자세한 내용은 JSDoc Toolkit 문서를 참고하세요.
태그 | 설명 |
---|---|
@abstract
|
메서드를 추상으로 표시합니다. 메서드를
/** @abstract */ foo.MyClass.prototype.abstractMethod = function() {}; |
@const
|
변수를 읽기 전용으로 표시합니다. 컴파일러는 자바스크립트 코드를 최적화하는 유형 선언은 선택사항입니다.
/** @const */ var MY_BEER = 'stout'; /** * My namespace's favorite kind of beer. * @const {string} */ mynamespace.MY_BEER = 'stout'; /** @const */ MyClass.MY_BEER = 'stout'; |
@constructor
|
함수를 생성자로 표시합니다.
컴파일러는 예를 들면 다음과 같습니다. /** * A rectangle. * @constructor */ function GM_Rect() { ... } |
@define
|
컴파일 시간에 컴파일러에서 재정의할 수 있는 상수를 나타냅니다.
왼쪽의 예에서 컴파일러에 --define='ENABLE_DEBUG=false'를 전달하여 ENABLE_DEBUG 값을 false로 변경할 수 있습니다.
정의된 상수의 유형은 숫자, 문자열 또는 부울일 수 있습니다.
정의는 전역 범위에서만 허용됩니다.
예를 들면 다음과 같습니다. /** @define {boolean} */ var ENABLE_DEBUG = true; /** @define {boolean} */ goog.userAgent.ASSUME_IE = false; |
@deprecated
|
함수, 메서드 또는 속성을 사용하여 더 이상 사용해서는 안 된다는 컴파일러 경고를 생성하도록 표시합니다. 예를 들면 다음과 같습니다. /** * 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
|
예를 들면 다음과 같습니다. /** * @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
|
enum의 유형을 지정합니다. enum은 속성이 관련 상수 집합을 구성하는 객체입니다. enum의 유형 라벨은 enum의 각 속성에 적용됩니다. 예를 들어 enum에 예를 들면 다음과 같습니다. /** * Enum for tri-state values. * @enum {number} */ project.TriState = { TRUE: 1, FALSE: -1, MAYBE: 0 }; |
@export
|
이 코드는 /** @export */ foo.MyPublicClass.prototype.myPublicMethod = function() { // ... };
goog.exportProperty(foo.MyPublicClass.prototype, 'myPublicMethod', foo.MyPublicClass.prototype.myPublicMethod); 컴파일되지 않은 코드로 기호를 내보냅니다. /** * @export * @type {SomeType} */의 약식 표현으로 작성할 수 있습니다.
|
@extends
|
클래스 또는 인터페이스를 다른 클래스에서 상속하는 것으로 표시합니다.
참고:
상속 구현 예는 클로저 라이브러리 함수 예를 들면 다음과 같습니다. /** * Immutable empty node list. * @constructor * @extends {goog.ds.BasicNodeList} */ goog.ds.EmptyNodeList = function() { ... }; |
@final
|
이 클래스는 확장할 수 없음을 나타냅니다. 메서드의 경우 서브클래스가 이 메서드를 재정의하도록 허용되지 않음을 나타냅니다. 예를 들면 다음과 같습니다. /** * A class that cannot be extended. * @final * @constructor */ sloth.MyFinalClass = function() { ... } /** * A method that cannot be overridden. * @final */ sloth.MyFinalClass.prototype.method = function() { ... }; |
@implements
|
생성자에 예를 들면 다음과 같습니다. /** * A shape. * @interface */ function Shape() {}; Shape.prototype.draw = function() {}; /** * @constructor * @implements {Shape} */ function Square() {}; Square.prototype.draw = function() { ... }; |
@implicitCast
|
이 주석은 extern 속성 선언에만 표시될 수 있습니다.
속성에 선언된 유형이 있지만 경고 없이 모든 유형을 할당할 수 있습니다. 속성에 액세스하면 선언된 유형의 값이 반환됩니다. 예를 들어 /** * @type {string} * @implicitCast */ Element.prototype.innerHTML; |
@inheritDoc
|
서브클래스의 메서드나 속성이 슈퍼클래스의 메서드나 속성을 의도적으로 가리며 정확하게 동일한 문서가 있음을 나타냅니다. 예를 들면 다음과 같습니다. /** @inheritDoc */ project.SubClass.prototype.toString = function() { ... }; |
@interface
|
함수를 인터페이스로 표시합니다. 인터페이스는 유형의 필수 멤버를 지정합니다. 인터페이스를 구현하는 모든 클래스는 인터페이스의 프로토타입에 정의된 모든 메서드와 속성을 구현해야 합니다.
컴파일러는 인터페이스가 인스턴스화되지 않는지 확인합니다. 예를 들면 다음과 같습니다. /** * A shape. * @interface */ function Shape() {}; Shape.prototype.draw = function() {}; /** * A polygon. * @interface * @extends {Shape} */ function Polygon() {}; Polygon.prototype.getSides = function() {}; |
@lends
|
객체 리터럴의 키를 다른 객체의 속성으로 취급해야 함을 나타냅니다. 이 주석은 객체 리터럴에만 표시되어야 합니다.
중괄호 안의 이름은 다른 주석에서와 같은 유형 이름이 아닙니다. 객체 이름입니다. 속성이 제공된 객체의 이름을 지정합니다.
예를 들어 이 주석에 대한 자세한 내용은 JSDoc 도구함 문서를 참고하세요. 예를 들면 다음과 같습니다. goog.object.extend( Button.prototype, /** @lends {Button.prototype} */ ({ isButton: function() { return true; } })); |
@license 또는 @preserve
|
표시된 파일의 컴파일된 코드 앞에 연결된 주석을 삽입하도록 컴파일러에 지시합니다. 이 주석을 사용하면 중요한 라이선스 (예: 법적 라이선스 또는 저작권 텍스트)를 변경하지 않고도 컴파일에서 유지할 수 있습니다. 줄바꿈은 유지됩니다. 예를 들면 다음과 같습니다. /** * @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
|
컴파일러에서 변수로 접으면 안 되는 속성을 나타냅니다. 예를 들면 다음과 같습니다. /** * A namespace. * @const */ var foo = {}; /** * @nocollapse */ foo.bar = 42; window['foobar'] = foo.bar; |
@nosideeffects
|
선언된 외부 함수를 호출할 때 부작용이 없음을 나타냅니다.
이 주석을 사용하면 반환 값이 사용되지 않는 경우 컴파일러에서 함수 호출을 삭제할 수 있습니다. 주석은 예를 들면 다음과 같습니다. /** @nosideeffects */ function noSideEffectsFn1() {} /** @nosideeffects */ var noSideEffectsFn2 = function() {}; /** @nosideeffects */ a.prototype.noSideEffectsFn3 = function() {}; |
@override
|
서브클래스의 메서드나 속성이 슈퍼클래스의 메서드나 속성을 의도적으로 숨김을 나타냅니다. 다른 주석이 포함되어 있지 않으면 메서드나 속성이 슈퍼클래스에서 주석을 자동으로 상속합니다. 예를 들면 다음과 같습니다. /** * @return {string} Human-readable representation of * project.SubClass. * @override */ project.SubClass.prototype.toString = function() { ... }; |
@package
|
구성원 또는 속성을 패키지 비공개로 표시합니다. 동일한 디렉터리의 코드만
공개 생성자에는 예를 들면 다음과 같습니다. /** * 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
|
메서드 인수, 함수 및 생성자 정의와 함께 사용하여 함수 인수의 유형을 지정합니다.
또는 매개변수 유형에 인라인으로 주석을 달 수 있습니다(예시의 함수 예를 들면 다음과 같습니다. /** * 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; }파괴적인 패턴의 매개변수에는 유형 주석 뒤에 유효한 JS 식별자인 이름을 사용할 수 있습니다. /** * @param {{name: string, age: number}} person */ function logPerson({name, age}) { console.log(`${name} is ${age} years old`); } |
@private
|
구성원을 비공개로 표시합니다. 동일한 파일의 코드만
예를 들면 다음과 같습니다. /** * Handlers that are listening to this logger. * @private {Array<Function>} */ this.handlers_ = []; |
@protected
|
구성원 또는 속성이 보호되고 있음을 나타냅니다.
예를 들면 다음과 같습니다. /** * 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
|
함수를 구조적 인터페이스로 표시합니다. 구조 인터페이스는 명목 예를 들면 다음과 같습니다. /** * 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
|
메서드 및 함수 정의의 반환 유형을 지정합니다.
또는 반환 유형에 인라인으로 주석을 달 수 있습니다(예시의 함수
extern에 없는 함수에 반환 값이 없으면 예를 들면 다음과 같습니다. /** * 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
|
예를 들면 다음과 같습니다. /** * @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
|
일반 유형을 참고하세요. 예를 들면 다음과 같습니다. /** * @param {T} t * @constructor * @template T */ Container = function(t) { ... }; |
@this
|
함수 내에서 키워드
컴파일러 경고를 방지하려면 예를 들면 다음과 같습니다. chat.RosterWidget.extern('getRosterElement', /** * Returns the roster widget element. * @this {Widget} * @return {Element} */ function() { return this.getComponent().getElement(); }); |
@throws
|
함수에서 발생한 예외를 문서화하는 데 사용됩니다. 유형 검사기는 현재 이 정보를 사용하지 않습니다. extern 파일에 선언된 함수가 부작용이 있는지 확인하는 데만 사용됩니다. 예를 들면 다음과 같습니다. /** * @throws {DOMException} */ DOMApplicationCache.prototype.swapCache = function() { ... }; |
@type
|
변수, 속성 또는 표현식의 유형을 식별합니다. 변수 또는 함수 매개변수를 선언할 때 두 번째 예에서와 같이 예를 들면 다음과 같습니다. /** * The message hex ID. * @type {string} */ var hexId = hexId; var /** string */ name = 'Jamie'; function useSomething(/** (string|number|!Object) */ something) { ... } |
@typedef
|
더 복잡한 유형의 별칭을 선언합니다. 현재 typedef는 함수 내부가 아닌 최상위 수준에서만 정의할 수 있습니다. 새로운 유형 추론에서 이 제한을 해결했습니다. 예를 들면 다음과 같습니다. /** @typedef {(string|number)} */ goog.NumberLike; /** @param {goog.NumberLike} x A number or a string. */ goog.readNumber = function(x) { ... } |
@unrestricted
|
클래스가 예를 들면 다음과 같습니다. /** * @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 |
유형 표현식
유형 표현식을 사용하여 변수, 속성, 표현식 또는 함수 매개변수의 데이터 유형을 지정할 수 있습니다. 유형 표현식은 아래에 설명된 유형 연산자의 조합을 포함하는 중괄호('{ }')로 구성됩니다.
@param
태그와 함께 유형 표현식을 사용하여 함수 매개변수의 유형을 선언합니다. @type
태그와 함께 유형 표현식을 사용하여 변수, 속성 또는 표현식의 유형을 선언합니다.
코드에 유형을 더 많이 지정할수록 컴파일러에서 더 많은 최적화를 수행할 수 있고 더 많은 실수를 발견할 수 있습니다.
컴파일러는 이러한 주석을 사용하여 프로그램을 유형 확인합니다.
클로저 컴파일러는 프로그램의 모든 표현식 유형을 파악할 수 있다고 약속하지 않습니다. 변수가 사용되는 방식과 선언에 연결된 유형 주석을 살펴보는 것이 최선의 방법입니다. 그런 다음 여러 유형의 추론 알고리즘을 사용하여 최대한 많은 표현식의 유형을 파악합니다. 이러한 알고리즘 중 일부는 간단합니다('x가 숫자이고 y = x;
가 보이면 y는 숫자'). 일부는 간접적입니다(예: f의 첫 번째 매개변수가 숫자를 받아야 하는 콜백으로 문서화되고 f(function(x) { /** ... */ });
가 표시되면 x는 숫자여야 함).
연산자 이름 | 구문 예 | 설명 |
---|---|---|
유형 이름 |
{boolean} {Window} {goog.ui.Menu}
|
유형 이름을 지정합니다. |
애플리케이션 유형 |
{Array<string>} 문자열로 구성된 배열입니다.
|
유형 인수 집합을 사용하여 유형을 매개변수화합니다. 자바 제네릭과 유사합니다. |
유형 공용체 |
{(number|boolean)} 숫자 또는 부울입니다. 필수 괄호를 확인합니다. |
값이 유형 A 또는 유형 B를 가질 수 있음을 나타냅니다. |
레코드 유형 |
{{myNum: number, myObject}}
유형이 number 인 myNum 속성과 모든 유형의 값을 가진 myObject 이라는 속성이 모두 포함된 익명 유형입니다.
|
값에 지정된 유형의 값과 함께 지정된 구성원이 있음을 나타냅니다. 중괄호는 유형 구문의 일부입니다. 예를 들어 |
null을 허용하는 유형 |
{?number} 숫자 또는 null 입니다.
|
값이 유형 A 또는 모든 객체 유형은 null 허용 여부 연산자로 선언되었는지 여부와 관계없이 기본적으로 null을 허용합니다. 객체 유형은 함수, 문자열, 숫자, 부울을 제외한 모든 값으로 정의됩니다. 객체 유형을 null을 허용하지 않도록 하려면 null을 허용하지 않는 연산자를 사용합니다. |
null을 허용하지 않는 유형 |
{!Object} 객체이지만 null 값은 아닙니다.
|
값이 null이 아닌 A 유형임을 나타냅니다. 함수와 모든 값 유형 (부울, 숫자, 문자열)은 null을 허용하지 않는 연산자로 선언되었는지 여부에 관계없이 기본적으로 null을 허용하지 않습니다. 값 또는 함수 유형을 null을 허용하는 값으로 설정하려면 Nullable 연산자를 사용합니다. |
함수 유형 |
{function(string, boolean)} 두 매개변수 (문자열, 부울)를 사용하며 알 수 없는 반환 값이 있는 함수 |
함수 및 함수 매개변수 유형을 지정합니다. |
함수 반환 유형 |
{function(): number} 매개변수를 사용하지 않고 숫자를 반환하는 함수입니다. |
함수의 반환 값 유형을 지정합니다. |
함수 this 유형 |
{function(this:goog.ui.Menu, string)} 하나의 매개변수 (문자열)를 가져오고 goog.ui.Menu의 컨텍스트에서 실행되는 함수입니다. |
함수 내의 this 값 유형을 지정합니다. |
함수 new 유형 |
{function(new:goog.ui.Menu, string)} 하나의 매개변수 (문자열)를 사용하고 'new' 키워드를 사용하여 호출할 때 새 goog.ui.Menu 인스턴스를 생성하는 함수입니다. |
생성자의 생성된 유형을 지정합니다. |
변수 매개변수 |
{function(string, ...number): number} 하나의 매개변수 (문자열)를 취한 다음 가변적인 수의 매개변수를 사용해야 하는 함수입니다. |
함수 유형이 가변적인 수의 매개변수를 사용하는 것을 나타내며, 변수 매개변수의 유형을 지정합니다. |
변수 매개변수 (@param 주석에서)
|
@param {...number} var_args 주석 처리된 함수에 대한 매개변수의 변수입니다. |
주석이 지정된 함수가 가변적인 매개변수 수를 허용하고 변수 매개변수의 유형을 지정함을 나타냅니다. |
@param 주석의 선택적 매개변수
|
@param {number=} opt_argument number 유형의 선택적 매개변수입니다.
|
메서드 호출에서 선택적 매개변수를 생략하면 인수의 값이 /** * 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; } |
함수 유형의 인수(선택사항) |
{function(?string=, number=)} 선택사항으로 null을 허용하는 문자열 1개와 선택적 숫자 하나를 인수로 사용하는 함수입니다. |
함수 유형의 인수는 선택사항임을 나타냅니다. 선택적 인수를 함수 호출에서 생략할 수 있습니다. 선택적 인수는 인수 목록의 선택적인 인수 앞에 올 수 없습니다. |
전체 유형 | {*} |
변수가 모든 유형을 사용할 수 있음을 나타냅니다. |
UNKNOWN 유형 | {?} |
변수가 모든 유형을 취할 수 있으며 컴파일러가 용도를 유형 검사해서는 안 된다는 것을 나타냅니다. |
유형 변환
값을 특정 유형으로 변환하려면 다음 구문을 사용하세요.
/** @type {!MyType} */ (valueExpression)표현식 괄호는 항상 필수입니다.
일반 유형
자바와 마찬가지로 클로저 컴파일러는 일반 유형, 함수, 메서드를 지원합니다. 제네릭은 다양한 유형의 객체에서 작동하면서 컴파일 시간 유형 안전성을 유지합니다.
제네릭을 사용하여 특정 유형의 객체에 대한 참조를 보유하는 일반화된 컬렉션과 특정 유형의 객체에 대해 작동하는 일반화된 알고리즘을 구현할 수 있습니다.
일반 유형 선언
유형을 유형의 생성자 (클래스의 경우) 또는 인터페이스 선언 (인터페이스의 경우)에 @template
주석을 추가하여 유형을 일반으로 만들 수 있습니다. 예를 들면 다음과 같습니다.
/** * @constructor * @template T */ Foo = function() { ... };
@template T
주석은 Foo
이 템플릿 유형이 T
인 일반 유형임을 나타냅니다.
템플릿 유형 T
는 Foo
의 정의 범위 내의 유형으로 사용할 수 있습니다. 예를 들면 다음과 같습니다.
/** @return {T} */ Foo.prototype.get = function() { ... }; /** @param {T} t */ Foo.prototype.set = function(t) { ... };
get
메서드는 T
유형의 객체를 반환하고 set
메서드는 T
유형의 객체만 허용합니다.
일반 유형 인스턴스화
위의 예시를 재사용하면 다음과 같이 여러 가지 방법으로 Foo
의 템플릿 인스턴스를 만들 수 있습니다.
/** @type {!Foo<string>} */ var foo = new Foo(); var foo = /** @type {!Foo<string>} */ (new Foo());
위의 생성자 문 모두 템플릿 유형이 T
인 Foo
인스턴스를 string
생성합니다. 컴파일러는 foo
의 메서드를 호출하고 foo
의 속성에 액세스하도록 하여 템플릿 유형을 따릅니다. 예를 들면 다음과 같습니다.
foo.set("hello"); // OK. foo.set(3); // Error - expected a string, found a number. var x = foo.get(); // x is a string.
생성자 인수에 따라 인스턴스를 암시적으로 입력할 수도 있습니다.
다른 일반 유형인 Bar
을 생각해 보세요.
/** * @param {T} t * @constructor * @template T */ Bar = function(t) { ... }; var bar = new Bar("hello"); // bar is a Bar<string>
Bar
생성자의 인수 유형은 string
로 추론되므로 생성된 인스턴스 bar
는 Bar<string>
로 추론됩니다.
여러 템플릿 유형
제네릭에는 원하는 수의 템플릿 유형이 있을 수 있습니다. 다음 지도 클래스에는 두 가지 템플릿 유형이 있습니다.
/** * @constructor * @template Key, Val */ MyMap = function() { ... };
일반 유형의 모든 템플릿 유형은 동일한 @template
주석에 쉼표로 구분된 목록으로 지정해야 합니다. 템플릿 유형 주석의 순서가 중요하므로 템플릿 유형 이름의 순서가 중요합니다. 예를 들면 다음과 같습니다.
/** @type {MyMap<string, number>} */ var map; // Key = string, Val = number.
일반 유형의 불변
클로저 컴파일러는 불변 일반 입력을 적용합니다. 즉, 컨텍스트에서 Foo<X>
유형을 예상하는 경우 X
과 Y
가 다른 유형인 경우 Foo<Y>
유형을 전달할 수 없습니다. 예를 들면 다음과 같습니다.
/** * @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
일반 유형 상속
일반 유형은 상속될 수 있으며 템플릿 유형은 고정되거나 상속 유형에 전파될 수 있습니다. 다음은 상위 유형의 템플릿 유형을 수정하는 상속 유형의 예입니다.
/** * @constructor * @template T */ A = function() { ... }; /** @param {T} t */ A.prototype.method = function(t) { ... }; /** * @constructor * @extends {A<string>} */ B = function() { ... };
A<string>
를 확장하면 B
에 string
유형의 매개변수를 사용하는 method
메서드가 있습니다.
다음은 상위 유형의 템플릿 유형을 전파하는 상속 유형의 예입니다.
/** * @constructor * @template U * @extends {A<U>} */ C = function() { ... };
A<U>
를 확장하여 C
의 템플릿 인스턴스에는 템플릿 유형 U
의 매개변수를 사용하는 method
메서드가 포함됩니다.
인터페이스는 유사한 방식으로 구현되고 확장될 수 있지만, 단일 유형이 다른 템플릿 유형으로 동일한 인터페이스를 여러 번 구현할 수는 없습니다. 예를 들면 다음과 같습니다.
/** * @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
일반 함수 및 메서드
일반 유형과 마찬가지로 함수와 메서드는 정의에 @template
주석을 추가하여 일반화할 수 있습니다. 예를 들면 다음과 같습니다.
/** * @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