트리플 슬래시 디렉티브
트리플 슬래시 디렉티브 (Triple-Slash Directives)
트리플 슬래시 디렉티브(triple-slash directive)는 XML 태그 하나를 담고 있는 한 줄짜리 주석이에요. 이 주석의 내용이 컴파일러 디렉티브로 사용됩니다. 파일 간 의존성을 선언하거나, 라이브러리나 내장 타입을 가져와야 할 때 이 문법을 만나게 돼요.
트리플 슬래시 디렉티브는 해당 파일의 맨 위에서만 유효합니다. 디렉티브 앞에는 한 줄 또는 여러 줄 주석(다른 트리플 슬래시 디렉티브 포함)만 올 수 있어요. 문이나 선언 뒤에서 만나게 되면 일반 한 줄 주석으로 취급되고, 특별한 의미를 갖지 않습니다.
TypeScript 5.5부터 컴파일러는 reference 디렉티브를 생성하지 않으며, preserve="true"로 표시된 디렉티브가 아니라면 손으로 작성한 트리플 슬래시 디렉티브를 출력 파일로 방출하지 않아요.
출처: TypeScript 핸드북
/// <reference path="..." />
/// <reference path="..." /> 디렉티브는 이 그룹에서 가장 흔히 쓰입니다. 이는 파일 간의 의존성 선언 역할을 해요.
트리플 슬래시 레퍼런스는 컴파일러에게 컴파일 과정에 추가 파일을 포함하라고 지시합니다.
또한 out이나 outFile을 쓸 때 출력 순서를 정하는 방법으로도 쓰여요. 파일들은 전처리 단계를 거친 후 입력과 같은 순서로 출력 파일 위치에 방출됩니다.
입력 파일 전처리
컴파일러는 모든 트리플 슬래시 reference 디렉티브를 해석하기 위해 입력 파일에 전처리 단계를 수행합니다. 이 과정에서 추가 파일이 컴파일에 더해져요.
이 과정은 루트 파일 집합에서 시작합니다. 이들은 명령줄이나 tsconfig.json 파일의 files 목록에 지정된 파일 이름이에요. 루트 파일은 지정된 순서대로 전처리됩니다. 파일이 목록에 추가되기 전에 그 안의 모든 트리플 슬래시 reference가 처리되고, 그 대상 파일들이 포함되요. 트리플 슬래시 reference는 파일에서 등장하는 순서대로 깊이 우선(depth-first) 방식으로 해석됩니다.
트리플 슬래시 reference 경로가 상대 경로라면 그것을 포함하는 파일을 기준으로 해석됩니다.
오류
존재하지 않는 파일을 참조하면 오류가 됩니다. 파일이 자기 자신을 트리플 슬래시 reference로 가리켜도 오류가 돼요.
--noResolve 사용하기
컴파일러 플래그 noResolve를 지정하면 트리플 슬래시 reference가 무시됩니다. 파일을 추가하지도 않고, 주어진 파일의 순서를 바꾸지도 않아요.
/// <reference types="..." />
의존성 선언 역할을 하는 /// <reference path="..." /> 디렉티브와 비슷하게, /// <reference types="..." /> 디렉티브는 패키지에 대한 의존성을 선언합니다.
이 패키지 이름을 해석하는 과정은 import 문에서 모듈 이름을 해석하는 과정과 비슷해요. 트리플 슬래시 reference-types 디렉티브를 "선언 패키지를 위한 import"라고 생각하면 쉽습니다.
예를 들어 선언 파일에 /// <reference types="node" />를 포함하면, 이 파일이 @types/node/index.d.ts에 선언된 이름들을 사용한다는 뜻입니다. 따라서 이 패키지가 선언 파일과 함께 컴파일에 포함되어야 해요.
.ts 파일에서 @types 패키지에 대한 의존성을 선언할 때는 대신 명령줄이나 tsconfig.json에서 types를 쓰세요. 자세한 내용은 tsconfig.json 파일에서 @types, typeRoots, types 사용하기를 참고하면 돼요.
/// <reference lib="..." />
이 디렉티브는 파일이 기존 내장 lib 파일을 명시적으로 포함하게 해줍니다.
내장 lib 파일은 tsconfig.json 의 lib 컴파일러 옵션과 같은 방식으로 참조해요 (예: lib="es2015"라고 하고 lib="lib.es2015.d.ts"라고 하지 않는 식).
DOM API나 Symbol, Iterable 같은 내장 JS 런타임 생성자처럼 내장 타입에 의존하는 선언 파일 작성자에게는 트리플 슬래시 reference lib 디렉티브가 권장됩니다. 이전에는 이런 .d.ts 파일들이 그런 타입을 전방 선언이나 중복 선언으로 추가해야 했어요.
예를 들어 컴파일에 속한 파일 하나에 /// <reference lib="es2017.string" />를 추가하는 것은 --lib es2017.string으로 컴파일하는 것과 같습니다.
/// <reference lib="es2017.string" />
"foo".padStart(4);
/// <reference no-default-lib="true"/>
이 디렉티브는 파일을 기본 라이브러리 로 표시합니다. lib.d.ts와 그 변형 파일들의 맨 위에서 이 주석을 보게 될 거예요.
이 디렉티브는 컴파일러에게 기본 라이브러리(즉 lib.d.ts)를 컴파일에 포함하지 말라고 지시합니다. 그 영향은 명령줄에 noLib을 넘기는 것과 비슷해요.
또한 skipDefaultLibCheck를 넘기면 컴파일러가 /// <reference no-default-lib="true"/>가 있는 파일만 검사를 건너뛴다는 점도 알아두세요.
/// <amd-module />
기본적으로 AMD 모듈은 익명으로 생성됩니다. 번들러(예: r.js)처럼 결과 모듈을 처리하는 다른 도구를 쓰면 이 때문에 문제가 생길 수 있어요.
amd-module 디렉티브는 컴파일러에 선택적 모듈 이름을 넘길 수 있게 해줍니다:
amdModule.ts
/// <amd-module name="NamedModule"/>
export class C {}
그 결과 AMD define을 호출하는 과정에서 모듈에 NamedModule이라는 이름이 할당됩니다:
amdModule.js
define("NamedModule", ["require", "exports"], function (require, exports) {
var C = (function () {
function C() {}
return C;
})();
exports.C = C;
});
/// <amd-dependency />
참고: 이 디렉티브는 더 이상 사용되지 않아요(Deprecated). 대신
import "moduleName";문을 사용하세요.
/// <amd-dependency path="x" />는 결과 모듈의 require 호출에 주입해야 하는, TS가 아닌 모듈 의존성을 컴파일러에게 알려줍니다.
amd-dependency 디렉티브는 선택적 name 속성도 가질 수 있어요. 이는 amd-dependency에 선택적 이름을 넘길 수 있게 해줍니다:
/// <amd-dependency path="legacy/moduleA" name="moduleA"/>
declare var moduleA: MyType;
moduleA.callStuff();
생성된 JS 코드:
define(["require", "exports", "legacy/moduleA"], function (
require,
exports,
moduleA
) {
moduleA.callStuff();
});
preserve="true"
트리플 슬래시 디렉티브에 preserve="true"를 표시하면 컴파일러가 이를 출력에서 제거하지 않게 됩니다.
예를 들어 이들은 출력에서 지워져요:
/// <reference path="..." />
/// <reference types="..." />
/// <reference lib="..." />
하지만 이들은 보존됩니다:
/// <reference path="..." preserve="true" />
/// <reference types="..." preserve="true" />
/// <reference lib="..." preserve="true" />