Publishing
Publishing (npm으로 배포하기)
이 가이드의 과정을 따라 선언 파일을 작성했다면, 이제 그것을 npm에 배포할 차례예요. 선언 파일을 npm에 배포하는 방법은 크게 두 가지가 있습니다.
- 자기 npm 패키지에 포함(bundling)시키기
- npm의 @types 조직에 배포하기
타입이 소스 코드에서 생성된다면 타입을 소스 코드와 함께 배포하세요. TypeScript 프로젝트와 JavaScript 프로젝트 모두 declaration으로 타입을 생성할 수 있어요.
그렇지 않다면 DefinitelyTyped에 제출할 것을 권장합니다. npm의 @types 조직에 배포되어요.
출처: TypeScript 핸드북
npm 패키지에 선언 포함하기
패키지에 main .js 파일이 있다면, package.json에 메인 선언 파일도 함께 지정해 줘야 해요. types 속성을 포함하고 있는 선언 파일을 가리키도록 설정하세요. 예를 들어:
{
"name": "awesome",
"author": "Vandelay Industries",
"version": "1.0.0",
"main": "./lib/main.js",
"types": "./lib/main.d.ts"
}
"typings" 필드는 types와 동의어이며, 똑같이 사용될 수 있다는 점을 참고하세요.
의존성 (Dependencies)
모든 의존성은 npm이 관리해요. 의존하는 모든 선언 패키지가 package.json의 "dependencies" 섹션에 알맞게 표시되도록 하세요. 예를 들어 Browserify와 TypeScript를 사용하는 패키지를 작성했다고 해 볼게요.
{
"name": "browserify-typescript-extension",
"author": "Vandelay Industries",
"version": "1.0.0",
"main": "./lib/main.js",
"types": "./lib/main.d.ts",
"dependencies": {
"browserify": "latest",
"@types/browserify": "latest",
"typescript": "next"
}
}
여기서 우리 패키지는 browserify와 typescript 패키지에 의존합니다. browserify는 선언 파일을 npm 패키지에 포함하지 않기 때문에, 그 선언을 위해 @types/browserify에 의존할 필요가 있었어요. 반면 typescript는 선언 파일을 패키지에 포함하므로 추가 의존성이 필요 없습니다.
우리 패키지는 그것들 각각의 선언을 노출하므로, browserify-typescript-extension 패키지의 사용자는 이 의존성들도 함께 가져야 해요. 그래서 "devDependencies"가 아니라 "dependencies"를 사용했어요. 그렇지 않으면 소비자가 그 패키지들을 수동으로 설치해야 하기 때문입니다. 만약 단순한 명령줄 애플리케이션을 작성했고 라이브러리로 사용될 것을 기대하지 않는다면, devDependencies를 썼을 수도 있어요.
주의해야 할 신호 (Red flags)
/// <reference path="..." />
선언 파일에서 /// <reference path="..." />를 사용하지 마세요.
/// <reference path="../typescript/lib/typescriptServices.d.ts" />
....
대신 /// <reference types="..." />를 사용하세요.
/// <reference types="typescript" />
....
자세한 내용은 의존성 사용하기 섹션을 다시 확인해 보세요.
의존하는 선언 패키징하기
타입 정의가 다른 패키지에 의존한다면:
- 자기 것과 합치지 마세요. 각각 자기 파일에 두세요.
- 선언을 자기 패키지에 복사하지도 마세요.
- 그 패키지가 자기 선언 파일을 패키징하지 않는다면, npm 타입 선언 패키지에 의존하세요.
typesVersions로 버전 선택하기
TypeScript가 package.json 파일을 열어 어떤 파일들을 읽어야 할지 알아낼 때, 먼저 typesVersions라는 필드를 확인해요.
폴더 리다이렉트 (* 사용)
typesVersions 필드를 가진 package.json은 이렇게 생겼을 거예요.
{
"name": "package-name",
"version": "1.0.0",
"types": "./index.d.ts",
"typesVersions": {
">=3.1": { "*": ["ts3.1/*"] }
}
}
이 package.json은 TypeScript에게 먼저 현재 TypeScript 버전을 확인하라고 지시해요. 3.1 이상이라면, TypeScript는 패키지에 상대적으로 import한 경로를 알아내서 패키지의 ts3.1 폴더에서 읽어들입니다.
그게 바로 { "*": ["ts3.1/*"] }이 뜻하는 것이에요. path 매핑에 익숙하다면, 정확히 그렇게 동작합니다.
위 예시에서 "package-name"에서 import한다면, TypeScript 3.1로 실행 중일 때 TypeScript는 [...]/node_modules/package-name/ts3.1/index.d.ts(및 기타 관련 경로)에서 해석하려고 시도해요. package-name/foo에서 import한다면 [...]/node_modules/package-name/ts3.1/foo.d.ts와 [...]/node_modules/package-name/ts3.1/foo/index.d.ts를 찾게 됩니다.
그럼 이 예시에서 TypeScript 3.1로 실행하지 않는다면 어떨까요? typesVersions의 어떤 필드도 매칭되지 않으면 TypeScript는 types 필드로 폴백하므로, 여기서 TypeScript 3.0 이하는 [...]/node_modules/package-name/index.d.ts로 리다이렉트됩니다.
파일 리다이렉트
한 번에 단일 파일에 대해서만 해석을 바꾸고 싶다면, 정확한 파일 이름을 전달해서 그 파일을 다르게 해석하도록 TypeScript에 알려줄 수 있어요.
{
"name": "package-name",
"version": "1.0.0",
"types": "./index.d.ts",
"typesVersions": {
"<4.0": { "index.d.ts": ["index.v3.d.ts"] }
}
}
TypeScript 4.0 이상에서는 "package-name"에 대한 import가 ./index.d.ts로 해석되고, 3.9 이하에서는 "./index.v3.d.ts로 해석돼요.
리다이렉션은 패키지의 외부 API에만 영향을 준다는 점을 참고하세요. 프로젝트 내부의 import 해석은 typesVersions의 영향을 받지 않습니다. 예를 들어 앞선 예시에서 import * as foo from "./index"를 포함한 d.ts 파일은 여전히 index.d.ts로 매핑되고 index.v3.d.ts로는 매핑되지 않는 반면, import * as foo from "package-name"을 import하는 다른 패키지는 index.v3.d.ts를 얻게 됩니다.
매칭 동작 (Matching behavior)
TypeScript가 컴파일러&언어의 버전이 매칭되는지 결정하는 방식은 Node의 semver 범위를 사용해요.
여러 필드 (Multiple fields)
typesVersions는 여러 필드를 지원하며, 각 필드 이름은 매칭할 범위로 지정합니다.
{
"name": "package-name",
"version": "1.0",
"types": "./index.d.ts",
"typesVersions": {
">=3.2": { "*": ["ts3.2/*"] },
">=3.1": { "*": ["ts3.1/*"] }
}
}
범위는 겹칠 수 있기 때문에, 어떤 리다이렉트가 적용될지 결정하는 것은 순서에 따라 달라져요. 즉 위 예시에서는 >=3.2와 >=3.1 매처가 모두 TypeScript 3.2 이상을 지원하지만, 순서를 뒤집으면 동작이 달라질 수 있으므로 위 예시는 아래와 동일하지 않습니다.
{
"name": "package-name",
"version": "1.0",
"types": "./index.d.ts",
"typesVersions": {
// NOTE: this doesn't work!
">=3.1": { "*": ["ts3.1/*"] },
">=3.2": { "*": ["ts3.2/*"] }
}
}
@types에 배포하기
@types 조직 아래의 패키지는 types-publisher 도구를 사용해 DefinitelyTyped에서 자동으로 배포됩니다. 여러분의 선언을 @types 패키지로 배포하려면 DefinitelyTyped에 풀 리퀘스트를 제출하세요. 자세한 내용은 기여 가이드라인 페이지에서 확인할 수 있어요.