⇒ 이러한 프레임워크, 라이브러리는 타입스크립트 프로젝트를 자동 생성해주기 때문!
npm init -y
y
옵션을 붙이지 않고 npm init
을 실행할 경우, 위 양식에 대해 일일이 값을 입력해야 하지만, y
옵션을 사용할 경우, default값으로 설정된 package.json 파일을 생성해준다. (y는 "yes"라는 의미)
npm install -D typescript
D
옵션을 사용하여, devDependencies에 타입스크립트를 설치해준다.
const hello = () => console.log("hi");
컴파일이 잘 되는 지 확인해보기 위해 임의로 함수를 작성해본다.
tsconfig.json 파일은 이 디렉토리가 TypeScript 프로젝트임을 나타낸다.
tsconfig.json은 TypeScript 프로젝트를 컴파일하는 데 필요한 루트 파일과 컴파일러 옵션을 지정한다.
"include": ["src"]
include의 배열 안에 자바스크립트로 컴파일하고 싶은 모든 디렉토리를 넣어주면 된다.
// tsconfig.json
"compilerOptions": {
"outDir": "build"
}
build
폴더에 JS파일이 생성되도록 설정하였다.
// package.json
"scripts": {
"build": "tsc"
},
// terminal
npm run build
package.json을 위와 같이 작성한 후, 터미널에서 npm run build
를 실행하면 tsc가 작동한다.
src 디렉토리 속 ts 파일들이 js 파일로 컴파일되어 build 디렉토리에 저장되는 것을 확인할 수 있다
// index.ts
const hello = () => console.log("hi");
// index.js
var hello = function () { return console.log("hi"); };
index.js을 확인해보면, index.ts에서 작성한 함수 형태와 다른 것을 확인할 수 있다.
이는 타입스크립트가 낮은 버전의 자바스크립트 코드로 컴파일한 것이다.
⇒ 어디에서든 이해할 수 있는 호환성 좋은 자바스크립트 코드로 컴파일된 것
✨ 그러나, 어떤 버전의 자바스크립트로 컴파일할 지는 변경이 가능하다!
"compilerOptions": {
"target": "ES6"
}
target
은 타입스크립트 컴파일 후의 자바스크립트 버전을 결정한다. (기본값 ES3)
만약 코드가 이전 환경에 배포된 경우 더 낮은 target
을 설정하거나 최신 환경에서 코드 실행이 보장되는 경우 더 높은 target
을 설정하도록 선택할 수 있다.
화살표 함수는 ES3에서는 지원하지 않기 때문에 함수 표현식으로 컴파일이 된다.
// index.ts
class Block {
constructor(private data: string) {}
static hello() {
return "hi";
}
}
만약 target
값이 ES3
인 상태에서 class 문법을 컴파일하면?
// index.js
var Block = /** @class */ (function () {
function Block(data) {
this.data = data;
}
Block.hello = function () {
return "hi";
};
return Block;
}());
타입스크립트가 클래스가 존재하지 않는 버전의 자바스크립트에서 클래스를 시뮬레이션해준다.
ES3와 같이 낮은 버전으로 설정할 경우 코드가 너무 길어질 수 있으며, ES2022와 같이 지나치게 최신버전으로 설정할 경우 호환성 문제가 발생할 수 있다.
⇒ ✨ 대부분의 nodeJS와 브라우저에서 ES6를 지원하므로, target
은 ES6로 설정하는 것이 가장 이상적이다.
TypeScript에는 내장 JS API(예: Math
)에 대한 기본 유형 정의 세트와 브라우저 환경에서 발견되는 항목에 대한 유형 정의(예: document
)가 포함되어 있다.
⇒ 이로 인해 lib
옵션으로 어떤 환경에서 코드를 실행할 지 지정할 수 있다.
만일 target
을 ES5
으로 설정한 상태에서 ES6에서 지원하는 Promise를 사용하고 싶다면, lib
배열에 ES6
를 추가해야 한다.
"compilerOptions": {
"lib": ["ES6", "DOM"]
}
lib
옵션에 DOM
을 추가하고 나면, document
, window
, localStorage
등의 객체를 사용할 수 있다.
document.querySelector
를 입력한 후 command를 눌러 클릭하면, lib.dom.d.ts 파일로 이동하게 된다.
해당 파일은 node_modules > typescript > lib 에 위치해 있으며, document
객체에 포함된 메서드들의 타입이 정의되어 있음을 확인할 수 있다.
⇒ ✨ lib.dom.d.ts은 dom 환경에서 사용할 수 있는 메서드 및 이벤트의 타입을 정의해둔 정의 파일 (Declaration File)!
⇒ ✨ 정의 파일이 있기 때문에 document
객체에 포함된 메서드의 타입을 따로 정의하지 않아도 메서드를 사용할 수 있는 것!
위처럼 localStorage.setItem()
작성 시, 인자의 타입과 return 타입 및 메서드에 대한 간단한 설명을 확인할 수 있다!
모든 엄격한 타입 검사 옵션을 활성화한다.
"compilerOptions": {
"strict": true
}
strict 모드를 활성화할 경우, 프로그램 정확성을 더 강력하게 보장하는 광범위한 타입 검사가 동작한다.
// myPackage.js
export function init(config) {
return true;
}
export function exit(code) {
return code + 1
}
myPackage.js가 node_modules의 자바스크립트의 모듈이라고 가정해보자.
myPackage.js 파일에 적힌 자바스크립트 코드의 타입을 타입스크립트는 알 수가 없다.
이 상태에서 index.ts 파일에서 myPackage를 node의 모듈인 것처럼 사용한다면?
// index.ts
import { init } from "myPackage";
// Err: Could not find a declaration file for moodule 'myPackage'.
정의 파일을 찾을 수 없다는 에러가 발생한다.
⇒ ✨ myPackage.d.ts 파일(정의 파일)을 만들어 타입을 정의해주어야 한다!
JavaScript 코드를 TypeScript에게 설명해주는 파일
TypeScript에는 내장 JS API(예: Math
)에 대한 기본 유형 정의 세트와 브라우저 환경에서 발견되는 항목에 대한 유형 정의(예: document
)가 포함되어 있다.
⇒ 정의 파일이 내장되어 있으므로, lib
옵션에서 환경 설정을 해 줄 경우, 따로 정의 파일을 만들지 않아도 된다!
우리가 사용하는 프레임워크, 라이브러리 등의 패키지는 타입스크립트가 아닌 자바스크립트로 만들어져있다.
그러므로 자바스크립트로 만들어진 라이브러리를 타입스크립트 프로젝트에서 사용하려면, 타입 정의가 필요하다.
// myPackage.d.ts
interface Config {
url: string;
}
declare module "myPackage" {
function init(config: Config): boolean;
function exit(code: number): number;
}
d.ts 파일에서 모듈에 대한 call signature를 작성해 준다.
정의 파일을 작성하고 나면, 타입스크립트가 함수 init
의 타입을 알고 있기 때문에 더 이상 에러가 발생하지 않게 된다.
함수 init
과 exit
에 대한 타입이 d.ts파일에 정의되어 있으므로, 함수 init
과 exit
를 사용할 때 따로 타입을 작성하지 않아도 된다.
한 프로젝트 안에 자바스크립트 파일과 타입스크립트 파일이 공존하는 경우를 종종 볼 수 있다. (ex. JS 프로젝트를 TS 프로젝트로 이전하는 경우)
만약 ts 파일에서 js 파일을 import하려 한다면?
// index.ts
import { init, exit } from "./myPackage";
// Err: './myPackage' 모듈을 찾을 수 없습니다.
에러가 발생한다.
// tsconfig.json
"compilerOptions": {
"allowJs": true
}
allowJs
옵션을 true
로 설정할 경우, TypeScript 프로젝트 내에서 JavaScript 파일을 import할 수 있게 된다.
다시 index.ts를 보면 import문에서 더 이상 에러가 발생하지 않음을 확인할 수 있으며, myPackage.js의 함수 init
코드를 분석하여 init
의 타입을 추론해주는 모습까지 확인할 수 있다.
// @ts-check
를 추가하여 TypeScript가 JavaScript 코드를 분석하도록 할 수 있다.
이러한 오류를 무시하고 싶다면 // @ts-ignore
또는 // @ts-expect-error
를 추가하여 특정 줄의 오류를 무시할 수 있다.
myPackage.js
// @ts-check
export function init(config) {
return true;
}
export function exit(code) {
return code + 1;
}
// @ts-check
를 .js파일의 첫 번째 줄에 추가하면 TypeScript가 오류를 발생시킨다.
myPackage.js
// @ts-check
// Err: 형식 주석은 TypeScript 파일에서만 사용할 수 있습니다.
export function init(config: object) {
return true;
}
export function exit(code) {
return code + 1;
}
이는 js 파일이기 때문에 타입을 작성할 수 없다!
자바스크립트 코드를 건들지 않은 채, 타입스크립트가 제공하는 보호 장치를 사용하고 싶다면?
⇒ ✨ JSDoc 이용!
JavaScript 파일에 주석을 사용하여 type 정보를 제공할 수 있는 문법
함수 위에 주석으로 작성하면 된다.
myPackage.js
// @ts-check
/**
* Initializes the project
* @param {object} config
* @param {boolean} config.debug
* @param {string} config.url
* @returns {boolean}
*/
export function init(config) {
return true;
}
/**
* Exits the program
* @param {number} code
* @returns {number}
*/
export function exit(code) {
return code + 1;
}
params 타입과 return 타입을 작성하면 타입스크립트가 해당 주석을 감지하여 타입을 체크해준다.
물론, ts 파일이 아닌 js 파일이므로 브라우저에서는 문제없이 실행된다.
myPackage.js에서 JSDoc을 작성한 후, index.ts에서 init
을 사용해보면 작성했던 JSDoc 내용을 확인할 수 있다.