이번 섹션에서는 기존의 JavaScript 프로젝트를 TypeScript 프로젝트로 변환하는 방법을 알아보도록 하겠습니다.

가정해 봅시다. TypeScript로 변환해야 할 몇 개의 JavaScript 파일이 있습니다. TypeScript 파일은 컴파일 시 같은 이름의 JavaScript 파일을 생성하게 되므로, 원본 JavaScript 파일을 TypeScript가 덮어쓰지 않도록 별도의 디렉터리에 보관해야 합니다. 또한, 출력 파일들은 ‘dist’라는 이름의 출력 디렉터리에 보관할 것입니다.

이 튜토리얼에서 우리는 다음과 같은 디렉터리 구조를 가질 것입니다:

JS에서 TS로의 마이그레이션을 위해 우리는 다음 단계를 따를 것입니다:

1. 프로젝트에 tsconfig.json 파일 추가하기
2. 빌드 도구와 통합하기
3. 모든 .js 파일을 .ts 파일로 변경하기
4. 오류 확인하기

프로젝트에 tsconfig.json 파일 추가하기

우선, 우리 프로젝트에 tsconfig.json 파일을 추가합시다. 이 파일은 프로젝트의 컴파일 옵션 관리와 포함 및 배제할 파일을 정의합니다.

예시: tsconfig.json 복사하기

{
    "compilerOptions": {
        "outDir": "./dist",
        "allowJs": true,
        "target": "es5"
    },
        "include": [
        "./src/**/*"
    ]
}

위의 설정 파일에서 src 폴더의 모든 파일을 포함시켰습니다. 이는 “include” 옵션을 사용하여 지정됩니다. compilerOptions의 outDir은 출력 파일들을 ‘dist’라는 폴더로 리디렉션한다는 것을 명시합니다. allowJs 옵션은 모든 JS 파일을 허용한다는 것을, target 옵션은 모든 JavaScript 구문을 ECMAScript 5로 번역하라는 것을 나타냅니다.

빌드 도구와 통합하기

대부분의 JavaScript 프로젝트는 webpack이나 gulp 같은 통합된 빌드 도구를 가지고 있습니다.

webpack과 통합하기 위해서는,

a) 터미널에서 다음 명령어를 실행하세요:

npm install awesome-typescript-loader source-map-loader

awesome-typescript-loader는 TypeScript 로더이며, source-map-loader는 소스 코드 디버깅에 사용됩니다.

b) webpack.config.js 파일의 module config 속성을 편집하여 이러한 두 로더를 포함시키세요:

예시: webpack.config.js 복사하기

module: {
    loaders: [
        // All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'.
        { test: /\.tsx?$/, loader: "awesome-typescript-loader" }
    ],

    preLoaders: [
        // All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
        { test: /\.js$/, loader: "source-map-loader" }
    ]
}

Gulp, Grunt, Browserify와 같은 기타 빌드 도구에 대해서는 이전 섹션을 참조하세요.

.js 파일을 .ts 파일로 변환하기

첫 번째 .js 파일의 이름을 .ts로 바꾸세요. 마찬가지로 .jsx 파일의 이름을 .tsx로 변경하세요.

그렇게 하면 일부 코드에서 컴파일 오류가 발생할 수 있습니다.

오류 확인하기

TypeScript는 엄격한 타입 검사를 하므로, 기존 JavaScript 코드에서 오류가 발생할 수 있습니다.

몇 가지 예시입니다:

a) 너무 많거나 적은 인수를 가진 함수

function displayPerson(name, age, height) {
    let str1 = "Person named " + name + ",  " + age + " years old";
    let str2 = (height !== undefined) ? (" and " + height +  " feet tall") : '';
    console.log(str1 + str2);
}

displayPerson( "John", 32);

위 코드에는 displayPerson()이라는 세 개의 인수(이름, 나이, 키)를 가진 함수가 있습니다. 우리는 위 함수에 “John”과 23이라는 두 가지 값을 호출합니다. 위 함수는 JavaScript에서 완전히 유효합니다. 이는 JavaScript에서 함수에 예상되는 인수가 없는 경우 해당 인수에 undefined 값을 할당하기 때문입니다.

그러나 TypeScript에서는 같은 코드가 ‘error TS2554: Expected 3 arguments, but got 2.’라는 컴파일 오류를 발생시킵니다.

이를 해결하기 위해 인수 height에 선택적 매개변수 표시를 추가할 수 있습니다. 오류르 제거하는 동안 아래와 같이 코드에 주석을 추가할 수도 있습니다.

function displayPerson( name: string, age: number, height?: number) {
    let str1: string = "Person named " + name + ",  " + age + " years old";
    let str2: string = (height !== undefined) ? (" and " + height +  " feet tall") : '';
    
    console.log(str1 + str2);
}

b) JavaScript에서 다음과 같은 객체를 고려하십시오:

let employee = {};
employee.code = 10;
employee.name = "John";

console.log(employee);

TypeScript에서는 다음과 같은 오류가 발생할 것입니다:

error TS2339: Property ‘code’ does not exist on type ‘{}’.

error TS2339: Property ‘name’ does not exist on type ‘{}’.

이를 해결하기 위해서는, 객체 내부에 속성들을 이동시킬 수 있습니다.

let employee = {
    code: 10,
    name: "John"
};

또는 인터페이스를 생성할 수 있습니다:

interface Employee {
    code: number,
    name: string
}

let empObj = {} as Employee;
empObj.code = 10;
empObj.name = "John";

타사 JavaScript 라이브러리 사용하기

대부분의 JavaScript 프로젝트는 jQuery나 Lodash와 같은 타사 라이브러리를 사용합니다. TypeScript는 이러한 라이브러리의 모든 객체 유형을 알아야 파일을 컴파일할 수 있습니다. 다행히, 대부분의 JavaScript 라이브러리에 대한 TypeScript 타입 정의 파일은 DefinitelyTyped에서 이미 이용 가능합니다. 그래서 우리는 이것들에 직접 유형을 추가할 필요가 없습니다. 할 일은 프로젝트에서 사용하는 각 라이브러리에 대한 타입을 설치하는 것입니다.

예를 들어, jQuery의 경우 정의를 설치하세요:

npm install @types/jquery

이용 가능한 모든 TypeScript 타입 정의 목록은 여기에서 볼 수 있습니다.

위의 모든 변경 사항을 JavaScript 프로젝트에 적용한 후, 빌드 도구를 실행하면 브라우저에서 실행할 수 있는 일반 JavaScript로 컴파일된 TypeScript 프로젝트를 갖게 될 것입니다.

그렇게 하면 기존 JavaScript 프로젝트를 TypeScript로 변환하기 위해 TypeScript를 사용하는 준비가 되었습니다.