Skip to content
This repository has been archived by the owner on Apr 23, 2020. It is now read-only.

Latest commit

Β 

History

History
423 lines (311 loc) Β· 18.5 KB

migrating-from-javascript.md

File metadata and controls

423 lines (311 loc) Β· 18.5 KB

TypeScriptλŠ” 곡백 μƒνƒœκ°€ μ•„λ‹™λ‹ˆλ‹€. JavaScript μƒνƒœκ³„λ₯Ό λ°”νƒ•μœΌλ‘œ κ΅¬μΆ•λ˜μ—ˆμœΌλ©°, μ˜€λŠ˜λ‚  λ§Žμ€ JavaScriptκ°€ μ‘΄μž¬ν•©λ‹ˆλ‹€. JavaScript μ½”λ“œ 베이슀λ₯Ό TypeScript둜 λ³€ν™˜ν•˜λŠ” 것은 λ‹€μ†Œ μ§€λ£¨ν•˜κΈ°λŠ” ν•˜μ§€λ§Œ 어렡지 μ•ŠμŠ΅λ‹ˆλ‹€. 이 νŠœν† λ¦¬μ–Όμ—μ„œ μ–΄λ–»κ²Œ μ‹œμž‘ν•˜λŠ”μ§€ μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€. TypeScript μ½”λ“œλ₯Ό μž‘μ„±ν•˜κΈ° μœ„ν•΄ ν•Έλ“œλΆμ„ μΆ©λΆ„νžˆ μ½μ—ˆλ‹€κ³  κ°€μ •ν•˜κ³  μ„€λͺ…ν•˜κ² μŠ΅λ‹ˆλ‹€.

React ν”„λ‘œμ νŠΈλ₯Ό λ³€ν™˜ν•˜κ³ μž ν•œλ‹€λ©΄, React λ³€ν™˜ κ°€μ΄λ“œλ₯Ό λ¨Όμ € μ½μ–΄λ³΄λŠ” 것을 μΆ”μ²œν•©λ‹ˆλ‹€.

디렉토리 μ„€μ •ν•˜κΈ° (Setting up your Directories)

일반 JavaScript둜 μž‘μ„±ν•˜λŠ” 경우, src, lib λ˜λŠ” dist 디렉터리에 μžˆλŠ” .js 파일이 JavaScriptλ₯Ό 직접 μ‹€ν–‰ν•œ λ‹€μŒ, μ›ν•˜λŠ” λŒ€λ‘œ μ‹€ν–‰ν–ˆμ„ κ°€λŠ₯성이 λ†’μŠ΅λ‹ˆλ‹€.

이 경우, μž‘μ„±ν•œ νŒŒμΌμ€ TypeScript에 μž…λ ₯으둜 μ‚¬μš©λ˜κ³ , 그둜 μΈν•œ 좜λ ₯을 μ‹€ν–‰ν•˜κ²Œ λ©λ‹ˆλ‹€. JSμ—μ„œ TS둜의 μ „ν™˜ν•˜λŠ” λ™μ•ˆ, TypeScriptκ°€ μž…λ ₯ νŒŒμΌμ„ 겹쳐 μ“°λŠ” 것을 λ°©μ§€ν•˜κΈ° μœ„ν•΄ μž…λ ₯ νŒŒμΌμ„ 뢄리할 ν•„μš”κ°€ μžˆμŠ΅λ‹ˆλ‹€. λ§Œμ•½ 좜λ ₯ 파일이 νŠΉμ • 디렉터리에 μœ„μΉ˜ν•΄μ•Ό ν•˜λŠ” 경우, κ·Έ μœ„μΉ˜κ°€ 좜λ ₯ 디렉터리가 λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€.

λ˜ν•œ JavaScriptμ—μ„œ λ²ˆλ“€λ§μ„ ν•˜κ±°λ‚˜ 바벨 같은 트랜슀파일러λ₯Ό μ‚¬μš©ν•˜λŠ” κ²ƒμ²˜λŸΌ, 쀑간 단계λ₯Ό μ‹€ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λŸ¬ν•œ 경우, μ΄λ ‡κ²Œ μ„€μ •λœ 폴더 ꡬ쑰λ₯Ό 가지고 μžˆμ„ 수 μžˆμŠ΅λ‹ˆλ‹€.

이 μ‹œμ λΆ€ν„°, 디렉터리가 λ‹€μŒκ³Ό 같이 μ„€μ •λ˜μ—ˆλ‹€κ³  κ°€μ •ν•˜κ² μŠ΅λ‹ˆλ‹€:

projectRoot
β”œβ”€β”€ src
β”‚   β”œβ”€β”€ file1.js
β”‚   └── file2.js
β”œβ”€β”€ built
└── tsconfig.json

λ§Œμ•½ src 디렉터리 λ°”κΉ₯에 tests 폴더가 μ‘΄μž¬ν•œλ‹€λ©΄, src와 tests 내뢀에 각각 tsconfig.json이 μ‘΄μž¬ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

μ„€μ • 파일 μž‘μ„±ν•˜κΈ° (Writing a Configuration File)

TypeScriptλŠ” μ–΄λ–€ νŒŒμΌμ„ ν¬ν•¨ν•˜κ³ , μ–΄λ–€ μ’…λ₯˜μ˜ 체크가 μˆ˜ν–‰λ˜μ–΄μ•Ό ν•˜λŠ”μ§€μ™€ 같은 ν”„λ‘œμ νŠΈ μ˜΅μ…˜μ„ κ΄€λ¦¬ν•˜κΈ° μœ„ν•΄, tsconfig.json이라 λΆˆλ¦¬λŠ” νŒŒμΌμ„ μ‚¬μš©ν•©λ‹ˆλ‹€. ν”„λ‘œμ νŠΈμ˜ λΌˆλŒ€λ₯Ό ꡬ성해 λ³΄κ² μŠ΅λ‹ˆλ‹€:

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

TypeScript에 λŒ€ν•œ λͺ‡ 가지 사항을 λͺ…μ‹œν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€:

  1. src λ””λ ‰ν„°λ¦¬μ—μ„œ ν•΄μ„λ˜λŠ” λͺ¨λ“  νŒŒμΌμ„ μ½μŠ΅λ‹ˆλ‹€ (include 포함).
  2. JavaScript νŒŒμΌμ„ μž…λ ₯으둜 ν—ˆμš©ν•©λ‹ˆλ‹€ (allowJs 포함).
  3. built λ‚΄λΆ€μ˜ λͺ¨λ“  좜λ ₯ νŒŒμΌμ„ λ‚΄λ³΄λƒ…λ‹ˆλ‹€ (outDir 포함).
  4. μ΅œμ‹  JavaScript ꡬ성을 ECMAScript 5와 같은 이전 λ²„μ „μœΌλ‘œ λ³€ν™˜ν•©λ‹ˆλ‹€(target μ‚¬μš©).

이 μ‹œμ μ—μ„œ, ν”„λ‘œμ νŠΈμ˜ λ£¨νŠΈμ—μ„œ tscλ₯Ό μž‘λ™μ‹œν‚€λ €λ©΄, λ°˜λ“œμ‹œ built 디렉터리에 μžˆλŠ” 좜λ ₯ 파일이 ν‘œμ‹œλ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€. built μ•ˆμ˜ λ ˆμ΄μ•„μ›ƒ νŒŒμΌμ€ src의 λ ˆμ΄μ•„μ›ƒκ³Ό 동일해야 ν•©λ‹ˆλ‹€. 이제 ν”„λ‘œμ νŠΈκ°€ TypeScript둜 μž‘λ™ν•  κ²ƒμž…λ‹ˆλ‹€.

초기 ν˜œνƒ (Early Benefits)

TypeScriptκ°€ ν”„λ‘œμ νŠΈλ₯Ό μ΄ν•΄ν•˜λŠ” κ²ƒμœΌλ‘œλΆ€ν„° λͺ‡ 가지 큰 ν˜œνƒμ„ 받을 수 μžˆμŠ΅λ‹ˆλ‹€. VS Code λ‚˜ Visual Studio 에디터λ₯Ό 열어보면, μžλ™μ™„μ„±κ³Ό 같은 툴링 지원을 λ°›λŠ” 것을 λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€. λ˜ν•œ λ‹€μŒ μ˜΅μ…˜μ΄ λ“€μ–΄ μžˆλŠ” νŠΉμ • 버그도 μž‘μ„ 수 μžˆμŠ΅λ‹ˆλ‹€:

  • ν•¨μˆ˜μ˜ λ§ˆμ§€λ§‰μ— return을 λΉ λœ¨λ¦¬λŠ” 것을 λ°©μ§€ν•˜λŠ” noImplicitReturns
  • switch λΈ”λ‘μ˜ case 사이에 breakλ₯Ό λΉ λœ¨λ¦¬λŠ” 것을 μ ˆλŒ€ μžŠμ§€ μ•ŠκΈ° μœ„ν•œ noFallthroughCasesInSwitch

λ˜ν•œ allowUnreachableCode 와 allowUnusedLabels 각각을 μ‚¬μš©ν•΄, TypeScriptλŠ” 도달할 수 μ—†λŠ” μ½”λ“œμ™€ 라벨에 λŒ€ν•œ κ²½κ³ λ₯Ό ν•  κ²ƒμž…λ‹ˆλ‹€.

λΉŒλ“œ 툴과 ν†΅ν•©ν•˜κΈ° (Integrating with Build Tools)

νŒŒμ΄ν”„λΌμΈμ— 더 λ§Žμ€ μ œμž‘ 단계가 μžˆμ„ 수 μžˆμŠ΅λ‹ˆλ‹€. 각각의 νŒŒμΌμ— 무언가λ₯Ό μ—°κ²°ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. κ°œλ³„ λΉŒλ“œ λ„κ΅¬λŠ” λ‹€λ₯΄μ§€λ§Œ, λΉŒλ“œ λ„κ΅¬μ˜ 핡심을 닀루기 μœ„ν•΄ μ΅œμ„ μ„ λ‹€ν•  κ²ƒμž…λ‹ˆλ‹€.

Gulp

λ§Œμ•½ Gulpλ₯Ό μ–΄λ–€ λ°©μ‹μœΌλ‘œ μ‚¬μš©ν•˜κ³  μžˆλ‹€λ©΄, TypeScript와 Gulpλ₯Ό μ‚¬μš©ν•˜λŠ” 방법과 Browserify, Babelify, Uglify 같은 일반적인 λΉŒλ“œ 툴과 ν†΅ν•©ν•˜λŠ” 방법에 λŒ€ν•œ νŠœν† λ¦¬μ–Όμ΄ μžˆμŠ΅λ‹ˆλ‹€. κ·Έκ³³μ—μ„œ 더 λ§Žμ€ λ‚΄μš©μ„ λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

Webpack

Webpack 톡합은 κ½€ κ°„λ‹¨ν•©λ‹ˆλ‹€. μ‰¬μš΄ 디버깅을 μœ„ν•΄ source-map-loader와 κ²°ν•©ν•œ TypeScript λ‘œλ”, awesome-typescript-loaderλ₯Ό μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€. λ‹¨μˆœνžˆ μ‹€ν–‰ν•˜κ³ 

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

λ‹€μŒ μ˜΅μ…˜μ—μ„œ webpack.config.js 파일과 λ³‘ν•©ν•˜μ„Έμš”:

module.exports = {
    entry: "./src/index.ts",
    output: {
        filename: "./dist/bundle.js",
    },

    // webpack의 좜λ ₯을 λ””λ²„κΉ…ν•˜κΈ° μœ„ν•΄ μ†ŒμŠ€λ§΅μ„ ν™œμ„±ν™” ν•©λ‹ˆλ‹€.
    devtool: "source-map",

    resolve: {
        // 해석 κ°€λŠ₯ν•œ ν™•μž₯자둜 '.ts' 와 '.tsx' λ₯Ό μΆ”κ°€ν•©λ‹ˆλ‹€.
        extensions: ["", ".webpack.js", ".web.js", ".ts", ".tsx", ".js"]
    },

    module: {
        loaders: [
            // '.ts' λ‚˜ '.tsx' ν™•μž₯자둜 λλ‚˜λŠ” λͺ¨λ“  νŒŒμΌμ€ 'awesome-typescript-loader'에 μ˜ν•΄ μ²˜λ¦¬λ©λ‹ˆλ‹€.
            { test: /\.tsx?$/, loader: "awesome-typescript-loader" }
        ],

        preLoaders: [
            // λͺ¨λ“  좜λ ₯ '.js' νŒŒμΌμ€ 'source-map-loader'에 μ˜ν•΄ 재처리된 μ†ŒμŠ€λ§΅μ„ κ°–μŠ΅λ‹ˆλ‹€.
            { test: /\.js$/, loader: "source-map-loader" }
        ]
    },

    // λ‹€λ₯Έ μ˜΅μ…˜λ“€...
};

awesome-typescript-loaderλŠ” λ‹€λ₯Έ λ‘œλ”κ°€ .js νŒŒμΌμ„ μ²˜λ¦¬ν•˜κΈ° 전에 μ‹€ν–‰λ˜μ–΄μ•Ό ν•œλ‹€λŠ” 점을 μœ μ˜ν•˜μ„Έμš”.

μ›Ή νŒ©μ„ μœ„ν•œ 또 λ‹€λ₯Έ TypeScript λ‘œλ”, ts-loader도 κ°™μŠ΅λ‹ˆλ‹€. μ—¬κΈ°μ—μ„œ λ‘˜ μ‚¬μ΄μ˜ 차이점을 읽을 수 μžˆμŠ΅λ‹ˆλ‹€.

λ¦¬μ•‘νŠΈμ™€ μ›Ή 팩 νŠœν† λ¦¬μ–Όμ—μ„œ μ›Ή 팩 μ‚¬μš©μ— κ΄€ν•œ 예제λ₯Ό λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

TypeScript 파일둜 μ΄λ™ν•˜κΈ° (Moving to TypeScript Files)

이제, TypeScript νŒŒμΌμ„ μ‚¬μš©ν•΄ μ‹œμž‘ν•  μ€€λΉ„κ°€ λ˜μ—ˆμ„ κ²ƒμž…λ‹ˆλ‹€. 첫 번째 λ‹¨κ³„λŠ” .js νŒŒμΌμ„ .ts 파일둜 이름을 λ°”κΎΈλŠ” κ²ƒμž…λ‹ˆλ‹€. 파일이 JSXλ₯Ό μ‚¬μš©ν•œλ‹€λ©΄ 이름을 .tsx둜 λ³€κ²½ν•˜μ„Έμš”.

κ·Έ 단계λ₯Ό λ§ˆμΉ˜μ…¨λ‚˜μš”? μ’‹μŠ΅λ‹ˆλ‹€! JavaScriptμ—μ„œ TypeScript둜 νŒŒμΌμ„ μ„±κ³΅μ μœΌλ‘œ λ§ˆμ΄κ·Έλ ˆμ΄μ…˜ ν–ˆμŠ΅λ‹ˆλ‹€!

λ‹Ήμ—°νžˆ, 그것이 λ°”λ‘œ λŠκ»΄μ§€μ§€λŠ” μ•Šμ„ κ²ƒμž…λ‹ˆλ‹€. TypeScriptλ₯Ό μ§€μ›ν•˜λŠ” μ—λ””ν„°λ‘œ νŒŒμΌμ„ 열어보면 (λ˜λŠ” tsc --prettyλ₯Ό μ‹€ν–‰ν•˜λ©΄), νŠΉμ • 쀄에 λΉ¨κ°„ κ΅¬λΆˆκ΅¬λΆˆν•œ 선이 λ‚˜νƒ€λ‚  κ²ƒμž…λ‹ˆλ‹€. Microsoft Word 같은 μ—λ””ν„°μ˜ λΉ¨κ°„ κ΅¬λΆˆκ΅¬λΆˆν•œ μ„ μ²˜λŸΌ μƒκ°ν•˜λ©΄ λ©λ‹ˆλ‹€. Wordκ°€ λ¬Έμ„œλ₯Ό μ—¬μ „νžˆ ν”„λ¦°νŠΈν•  수 μžˆλŠ” κ²ƒμ²˜λŸΌ, TypeScript도 μ—¬μ „νžˆ μ½”λ“œλ₯Ό 해석할 수 μžˆμŠ΅λ‹ˆλ‹€.

λ§Œμ•½ 그것이 λ„ˆλ¬΄ λŠμŠ¨ν•΄ 보인닀면, 더 μ—„κ²©ν•˜κ²Œ 행동할 수 μžˆμŠ΅λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, 였λ₯˜ λ°œμƒ μ‹œ JavaScriptλ₯Ό TypeScript둜 컴파일 ν•˜μ§€ μ•ŠμœΌλ €λ©΄, noEmitOnError μ˜΅μ…˜μ„ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬ν•œ μ˜λ―Έμ—μ„œ, TypeScriptλŠ” 이상적인 엄격함을 κ°–κ³  있고, μ›ν•˜λŠ” 만큼 κ·Έ 기쀀을 높일 수 μžˆμŠ΅λ‹ˆλ‹€.

μ΅œλŒ€ν•œ μ—„κ²©ν•œ μ„ΈνŒ…μ„ μ‚¬μš©ν•  κ³„νšμ΄λΌλ©΄, μ§€κΈˆ μ„€μ •ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€(더 μ—„κ²©ν•œ μ²΄ν¬ν•˜κΈ° μ°Έμ‘°). 예λ₯Ό λ“€μ–΄, TypeScriptκ°€ λͺ…μ‹œμ  μ„€λͺ… μ—†μ΄λŠ” νƒ€μž…μ„ any둜 μΆ”λ‘ ν•˜μ§€ μ•ŠκΈ°λ₯Ό μ›ν•œλ‹€λ©΄, νŒŒμΌμ„ μˆ˜μ •ν•˜κΈ° μ „ noImplicitAnyλ₯Ό μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€. λ‹€μ†Œ λΆ€λ‹΄μŠ€λŸ½κ²Œ 느껴질 수 μžˆμ§€λ§Œ, μž₯기적으둜 훨씬 μ΄λ“μž…λ‹ˆλ‹€.

였λ₯˜ μ œκ±°ν•˜κΈ° (Weeding out Errors)

μ–ΈκΈ‰ν–ˆλ˜ κ²ƒμ²˜λŸΌ, μ „ν™˜ ν›„ μ—λŸ¬ λ©”μ‹œμ§€κ°€ λœ¨λŠ” 것은 μ˜ˆμƒν•˜μ§€ λͺ»ν–ˆμŠ΅λ‹ˆλ‹€. μ€‘μš”ν•œ 점은 μ‹€μ œλ‘œ ν•˜λ‚˜ν•˜λ‚˜μ˜ 였λ₯˜λ₯Ό μ–΄λ–»κ²Œ μ²˜λ¦¬ν•  것인지 κ²°μ •ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. μ’…μ’… 이것이 합법적인 버그가 될 수 μžˆμ§€λ§Œ, λ•Œλ•Œλ‘œ TypeScriptμ—κ²Œ 무엇을 더 μž˜ν•˜λ €κ³  ν•˜λŠ”μ§€ μ„€λͺ…ν•΄μ•Ό ν•©λ‹ˆλ‹€.

λͺ¨λ“ˆλ‘œλΆ€ν„° import ν•˜κΈ° (Importing from Modules)

μ‹œμž‘ν•  λ•Œ Cannot find name 'require'., and Cannot find name 'define'. 같은 μ—λŸ¬κ°€ 많이 λ‚˜νƒ€λ‚  수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λŸ¬ν•œ 경우, λͺ¨λ“ˆμ„ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ•„λž˜μ˜ 선언을 톡해 TypeScriptμ—κ²Œ μ΄λŸ¬ν•œ κΈ°λŠ₯이 μ‘΄μž¬ν•œλ‹€κ³  λ‚©λ“μ‹œν‚¬ 수 μžˆμ§€λ§Œ

// For Node/CommonJS
declare function require(path: string): any;

λ˜λŠ”

// For RequireJS/AMD
declare function define(...args: any[]): any;

μ΄λŸ¬ν•œ ν˜ΈμΆœμ„ μ œκ±°ν•˜κ³  importλ₯Ό μœ„ν•œ TypeScript ꡬ문을 μ‚¬μš©ν•˜λŠ” 것이 더 λ‚«μŠ΅λ‹ˆλ‹€.

λ¨Όμ €, TypeScript module ν”Œλž˜κ·Έλ₯Ό μ„€μ •ν•¨μœΌλ‘œμ¨ λͺ¨λ“ˆ μ‹œμŠ€ν…œμ„ ν™œμ„±ν™”ν•΄μ•Ό ν•©λ‹ˆλ‹€. μœ νš¨ν•œ μ˜΅μ…˜μ€ commonjs, amd, system, 그리고 umdμž…λ‹ˆλ‹€.

λ§Œμ•½ λ‹€μŒκ³Ό 같은 Node/CommonJS μ½”λ“œλ₯Ό κ°–κ³  μžˆλ‹€λ©΄:

var foo = require("foo");

foo.doStuff();

λ˜λŠ” λ‹€μŒμ˜ RequireJS/AMD μ½”λ“œλ₯Ό κ°–κ³  μžˆλ‹€λ©΄:

define(["foo"], function(foo) {
    foo.doStuff();
})

그러면 λ‹€μŒμ˜ TypeScript μ½”λ“œλ₯Ό μž‘μ„±ν•΄μ•Ό ν•©λ‹ˆλ‹€:

import foo = require("foo");

foo.doStuff();

μ„ μ–Έ 파일 μ‹œμž‘ν•˜κΈ° (Getting Declaration Files)

λ§Œμ•½ TypeScript import둜 μ „ν™˜μ„ μ‹œμž‘ν–ˆλ‹€λ©΄, Cannot find module 'foo'. 같은 였λ₯˜κ°€ λ°œμƒν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ—¬κΈ°μ„œ λ¬Έμ œλŠ” 라이브러리λ₯Ό μ„€λͺ…ν•˜λŠ” μ„ μ–Έ 파일이 없을 κ°€λŠ₯성이 λ†’λ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€. λ‹€ν–‰νžˆ ν•΄κ²° 방법은 κ½€ μ‰½μŠ΅λ‹ˆλ‹€. λ§Œμ•½ TypeScriptκ°€ lodash 같은 νŒ¨ν‚€μ§€μ— λŒ€ν•΄ κ²½κ³ λ₯Ό λ°œμƒμ‹œν‚€λ©΄, κ·Έλƒ₯ μž‘μ„±ν•˜λ©΄ λ©λ‹ˆλ‹€

npm install -S @types/lodash

commonjs 말고 λ‹€λ₯Έ λͺ¨λ“ˆ μ˜΅μ…˜μ„ μ‚¬μš©ν•œλ‹€λ©΄, moduleResolution을 node둜 μ„€μ •ν•΄μ•Ό ν•©λ‹ˆλ‹€.

κ·Έ ν›„, lodashλ₯Ό λ¬Έμ œμ—†μ΄ import ν•  수 있고, μ •ν™•ν•˜κ²Œ μ™„μ„±ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

λͺ¨λ“ˆ export ν•˜κΈ° (Exporting from Modules)

μ „ν˜•μ μœΌλ‘œ, λͺ¨λ“ˆμ„ export ν•˜λŠ” 것은exports ν˜Ήμ€ module.exports 같은 값을 ν”„λ‘œνΌν‹°μ— μΆ”κ°€ν•˜λŠ” 것을 ν¬ν•¨ν•©λ‹ˆλ‹€. TypeScriptλŠ” μ΅œμƒμœ„-레벨의 export 문을 ν—ˆμš©ν•©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, ν•¨μˆ˜λ₯Ό μ΄λ ‡κ²Œ export ν–ˆλ‹€λ©΄:

module.exports.feedPets = function(pets) {
    // ...
}

그것을 λ‹€μŒκ³Ό 같이 μž‘μ„±ν•  수 μžˆμŠ΅λ‹ˆλ‹€:

export function feedPets(pets) {
    // ...
}

λ•Œλ‘œ exports 객체λ₯Ό μ™„μ „νžˆ μž¬μž‘μ„±ν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ•„λž˜ 예제처럼 μ¦‰μ‹œ ν˜ΈμΆœν•˜κΈ° μœ„ν•΄ μ΄λŸ¬ν•œ ν”ν•œ νŒ¨ν„΄μ„ μ‚¬μš©ν•©λ‹ˆλ‹€:

var express = require("express");
var app = express();

μ „μ—λŠ” μ΄λ ‡κ²Œ μž‘μ„±ν–ˆμ„ 수 μžˆμŠ΅λ‹ˆλ‹€:

function foo() {
    // ...
}
module.exports = foo;

TypeScriptμ—μ„œ, 이것을 export = ꡬ문을 μ‚¬μš©ν•˜μ—¬ λͺ¨λΈλ§ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

function foo() {
    // ...
}
export = foo;

λ„ˆλ¬΄ λ§Žμ€/λ„ˆλ¬΄ 적은 인수 (Too many/too few arguments)

λ•Œλ‘œ λ„ˆλ¬΄ λ§Žμ€/λ„ˆλ¬΄ 적은 인수λ₯Ό κ°–κ³  μžˆλŠ” ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•  λ•Œκ°€ μžˆμŠ΅λ‹ˆλ‹€. μ „ν˜•μ μΈ λ²„κ·Έμ΄μ§€λ§Œ, κ·ΈλŸ¬λ‚˜ λͺ‡λͺ‡ 경우, μ–΄λ– ν•œ λ§€κ°œλ³€μˆ˜λ₯Ό μ“°λŠ” λŒ€μ‹  arguments 객체λ₯Ό μ‚¬μš©ν•˜λŠ” ν•¨μˆ˜λ₯Ό μ„ μ–Έν•  수 μžˆμŠ΅λ‹ˆλ‹€:

function myCoolFunction() {
    if (arguments.length == 2 && !Array.isArray(arguments[1])) {
        var f = arguments[0];
        var arr = arguments[1];
        // ...
    }
    // ...
}

myCoolFunction(function(x) { console.log(x) }, [1, 2, 3, 4]);
myCoolFunction(function(x) { console.log(x) }, 1, 2, 3, 4);

이 경우, TypeScriptλ₯Ό μ‚¬μš©ν•΄μ„œ ν˜ΈμΆœμžμ—κ²Œ ν•¨μˆ˜ μ˜€λ²„λ‘œλ“œλ₯Ό μ‚¬μš©ν•΄ myCoolFunction이 ν˜ΈμΆœλ˜λŠ” 방법을 μ•Œλ €μ£Όμ–΄μ•Ό ν•©λ‹ˆλ‹€.

function myCoolFunction(f: (x: number) => void, nums: number[]): void;
function myCoolFunction(f: (x: number) => void, ...nums: number[]): void;
function myCoolFunction() {
    if (arguments.length == 2 && !Array.isArray(arguments[1])) {
        var f = arguments[0];
        var arr = arguments[1];
        // ...
    }
    // ...
}

myCoolFunction에 μ˜€λ²„λ‘œλ“œ μ‹œκ·Έλ‹ˆμ²˜ 두 개λ₯Ό μΆ”κ°€ν–ˆμŠ΅λ‹ˆλ‹€. 첫 번째 κ²€μ‚¬λŠ” myCoolFunction이 (numberλ₯Ό 인수둜 κ°–λŠ”) ν•¨μˆ˜μ™€ number 배열을 κ°€μ§„λ‹€λŠ” 것을 λͺ…μ‹œν•©λ‹ˆλ‹€. 두 번째 κ²€μ‚¬λŠ” myCoolFunction이 λ§ˆμ°¬κ°€μ§€λ‘œ ν•¨μˆ˜λ₯Ό 가지고, λ‚˜λ¨Έμ§€ μ—°μ‚°μž(...nums)λ₯Ό μ‚¬μš©ν•˜μ—¬ κ·Έ μ™Έμ˜ μΈμˆ˜λŠ” λͺ‡κ°œμ˜ μΈμˆ˜λ“  numberκ°€ λ˜μ–΄μ•Ό 함을 λͺ…μ‹œν•©λ‹ˆλ‹€.

순차적으둜 μΆ”κ°€λœ ν”„λ‘œνΌν‹° (Sequentially Added Properties)

μ–΄λ–€ μ‚¬λžŒλ“€μ€ 객체λ₯Ό μƒμ„±ν•˜κ³  λ‹€μŒκ³Ό 같이 λ™μ μœΌλ‘œ ν”„λ‘œνΌν‹°λ₯Ό μΆ”κ°€ν•˜λŠ” 것이 미관상 더 보기 μ’‹λ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€:

var options = {};
options.color = "red";
options.volume = 11;

TypeScriptλŠ” options을 ν”„λ‘œνΌν‹°κ°€ μ—†λŠ” {}둜 μΈμ‹ν–ˆκΈ° λ•Œλ¬Έμ— color와 volume을 ν• λ‹Ήν•  수 μ—†λ‹€κ³  ν•  κ²ƒμž…λ‹ˆλ‹€. λ§Œμ•½ 선언을 λ¦¬ν„°λŸ΄ 객체둜 λ³€κ²½ν•˜λ©΄, 였λ₯˜κ°€ λ°œμƒν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€:

let options = {
    color: "red",
    volume: 11
};

λ˜ν•œ options의 νƒ€μž…μ„ μ •μ˜ν•΄μ•Ό ν•˜κ³  객체 λ¦¬ν„°λŸ΄μ— λŒ€ν•œ νƒ€μž… 단언을 μΆ”κ°€ν•΄μ•Ό ν•©λ‹ˆλ‹€.

interface Options { color: string; volume: number }

let options = {} as Options;
options.color = "red";
options.volume = 11;

λŒ€μ‹ , options이 λ‹¨μˆœνžˆ νƒ€μž…anyλ₯Ό κ°–λŠ”λ‹€κ³  λͺ…μ‹œν•  수 μžˆλŠ”λ°, 이 방법은 κ°€μž₯ μ‰¬μš΄ λ°©λ²•μ΄μ§€λ§Œ κ°€μž₯ 적은 μž₯점을 가지고 μžˆμŠ΅λ‹ˆλ‹€.

any, Object, and {}

ObjectλŠ” λŒ€λΆ€λΆ„μ˜ 경우 κ°€μž₯ 일반적인 νƒ€μž…μ΄λ―€λ‘œ, 값이 μ–΄λ–€ ν”„λ‘œνΌν‹°λ„ κ°€μ§ˆ 수 μžˆλ‹€κ³  λ§ν•˜κΈ° μœ„ν•΄ Object λ‚˜ {}λ₯Ό μ‚¬μš©ν•˜κ³  싢을 수 μžˆμŠ΅λ‹ˆλ‹€. ν•˜μ§€λ§Œ anyκ°€ κ°€μž₯ μœ μ—°ν•œ νƒ€μž…μ΄λ―€λ‘œ, μ΄λŸ¬ν•œ κ²½μš°μ—λŠ” μ‹€μ œλ‘œ anyκ°€ κ°€μž₯ μ μ ˆν•œ νƒ€μž… μž…λ‹ˆλ‹€.

예λ₯Ό λ“€μ–΄, Objectλ₯Ό νƒ€μž…μœΌλ‘œ μ„ μ–Έν•œ 경우 toLowerCase()같은 λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•  수 μ—†μŠ΅λ‹ˆλ‹€. 더 일반적으둜 μ‚¬μš©ν•œλ‹€λŠ” 것은 νƒ€μž…μœΌλ‘œ 더 적은 일을 ν•  수 μžˆλ‹€λŠ” 것을 μ˜λ―Έν•˜μ§€λ§Œ, anyλŠ” μ–΄λ–€ 일이든 ν•  수 있게 ν•˜λŠ” λ™μ‹œμ— κ°€μž₯ 일반적인 νƒ€μž…μ΄λΌλŠ” μ μ—μ„œ νŠΉλ³„ν•©λ‹ˆλ‹€. 그것은 anyλ₯Ό ν˜ΈμΆœν•˜κ³ , κ΅¬μ„±ν•˜κ³ , ν”„λ‘œνΌν‹°μ— μ ‘κ·Όν•˜λŠ” λ“±μ˜ 일을 ν•  수 μžˆλ‹€λŠ” 것을 μ˜λ―Έν•©λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ anyλ₯Ό μ‚¬μš©ν•˜λ©΄ TypeScriptκ°€ μ œκ³΅ν•˜λŠ” λŒ€λΆ€λΆ„μ˜ νƒ€μž… 검사와 에디터 지원을 받을 수 μ—†λ‹€λŠ” 것을 λͺ…μ‹¬ν•˜μ„Έμš”.

λ§Œμ•½ Object와 {}둜 결정이 내렀지면, {}λ₯Ό 선택해야 ν•©λ‹ˆλ‹€. 이 λ‘˜μ€ 거의 κ°™μ§€λ§Œ, νŠΉμ • λ‚œν•΄ν•œ μƒν™©μ—μ„œ 기술적으둜 {}이 Object보닀 더 일반적인 νƒ€μž…μž…λ‹ˆλ‹€.

더 μ—„κ²©ν•œ μ²΄ν¬ν•˜κΈ° (Getting Stricter Checks)

TypeScriptλŠ” ν”„λ‘œκ·Έλž¨μ— λŒ€ν•œ μ•ˆμ •μ„±κ³Ό 뢄석을 μ œκ³΅ν•˜λŠ” νŠΉμ •ν•œ 검사λ₯Ό κ°–κ³  μžˆμŠ΅λ‹ˆλ‹€. TypeScript둜 μ½”λ“œλ² μ΄μŠ€λ₯Ό μ‹œμž‘ν•˜λ©΄, ν–₯μƒλœ μ•ˆμ „μ„±μ„ μœ„ν•œ 검사λ₯Ό ν™œμ„±ν™”ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

μ•”μ‹œμ μΈ anyλŠ” ν”Όν•˜κΈ° (No Implicit any)

μ–΄λ–€ νƒ€μž…μ΄μ–΄μ•Ό ν•˜λŠ”μ§€ TypeScriptκ°€ νŒŒμ•…ν•  수 μ—†λŠ” κ²½μš°κ°€ μžˆμŠ΅λ‹ˆλ‹€. μ΅œλŒ€ν•œ μœ μ—°ν•˜κ²Œ λŒ€μ‘ν•˜κΈ° μœ„ν•΄, κ·Έ μžλ¦¬μ— anyλ₯Ό μ‚¬μš©ν•˜κΈ°λ‘œ κ²°μ •ν•  κ²ƒμž…λ‹ˆλ‹€. 이것은 λ§ˆμ΄κ·Έλ ˆμ΄μ…˜μ—λŠ” μ’‹μ§€λ§Œ, anyλ₯Ό μ‚¬μš©ν•œλ‹€λŠ” 것은 λ‹€λ₯Έ κ³³μ—μ„œ 받을 수 μžˆλŠ” μ–΄λ– ν•œ νƒ€μž… μ•ˆμ •μ„±κ³Ό 툴링 지원도 받지 λͺ»ν•œλ‹€λŠ” 것을 μ˜λ―Έν•©λ‹ˆλ‹€. TypeScriptκ°€ 이런 뢀뢄에 ν”Œλž˜κ·Έμ™€ μ—λŸ¬λ₯Ό λ„μšΈ 수 μžˆλ„λ‘ noImplicitAnyμ˜΅μ…˜μ„ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

μ—„κ²©ν•œ null & undefined 검사 (Strict null & undefined Checks)

기본적으둜, TypeScriptλŠ” null κ³Ό undefined이 λͺ¨λ“  νƒ€μž…μ˜ 도메인에 μ‘΄μž¬ν•œλ‹€κ³  κ°€μ •ν•©λ‹ˆλ‹€. number둜 μ„ μ–Έλœ νƒ€μž…μ΄ null ν˜Ήμ€ undefined이 될 수 μžˆλ‹€λŠ” μ˜λ―Έμž…λ‹ˆλ‹€. null κ³Ό undefinedλŠ” JavaScript 와 TypeScript μ—μ„œ λΉˆλ²ˆν•œ 버그 원인이기 λ•Œλ¬Έμ—, TypeScript μ—λŠ” μ΄λŸ¬ν•œ 문제의 걱정을 λœμ–΄μ£ΌλŠ” strictNullChecks μ˜΅μ…˜μ΄ μžˆμŠ΅λ‹ˆλ‹€.

strictNullChecksκ°€ ν™œμ„±ν™”λ˜λ©΄, nullκ³Ό undefinedλŠ” 각각 nullκ³Ό undefinedλΌλŠ” 자체 μœ ν˜•μ„ κ°€μ Έμ˜΅λ‹ˆλ‹€. μ–΄λ–€ 것이 null이 될 κ°€λŠ₯성이 μžˆλŠ” μƒν™©μ—μ„œ, μ›λž˜ νƒ€μž…κ³Ό ν•¨κ»˜ μœ λ‹ˆμ–Έ νƒ€μž…μ„ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, λ§Œμ•½ numberλ‚˜ null이 될수 μžˆλŠ” 경우, number | null둜 νƒ€μž…μ„ μž‘μ„±ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

TypeScriptκ°€ null/undefined라고 생각할 수 μžˆλŠ” 값을 κ°–κ³  μžˆμ§€λ§Œ, νƒ€μž…μ— λŒ€ν•΄ 더 잘 μ•Œκ³  μžˆλŠ” 경우, ν›„μœ„ μ—°μ‚°μž !λ₯Ό μ‚¬μš©ν•΄ λ‹€λ₯΄κ²Œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

declare var foo: string[] | null;

foo.length;  // error - 'foo' is possibly 'null'

foo!.length; // okay - 'foo!' just has type 'string[]'

μ•žμœΌλ‘œ, strictNullChecksλ₯Ό μ‚¬μš©ν•  λ•Œ, μ˜μ‘΄μ„±μ΄ strictNullChecksλ₯Ό μ‚¬μš©ν•˜λ„λ‘ μ—…λ°μ΄νŠΈ λ˜μ–΄μ•Ό ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

this에 λŒ€ν•œ μ•”μ‹œμ  any ν”Όν•˜κΈ° (No Implicit any for this)

this ν‚€μ›Œλ“œλ₯Ό 클래슀 λ°–μ—μ„œ μ‚¬μš©ν•  λ•Œ, 기본적으둜 any νƒ€μž…μ„ κ°€μ§‘λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, Point 클래슀λ₯Ό 상상해 λ³΄μ„Έμš”, 그리고 λ©”μ„œλ“œλ‘œ μΆ”κ°€ν•˜κ³  싢은 ν•¨μˆ˜λ₯Ό μƒμƒν•΄λ³΄μ„Έμš”:

class Point {
    constructor(public x, public y) {}
    getDistance(p: Point) {
        let dx = p.x - this.x;
        let dy = p.y - this.y;
        return Math.sqrt(dx ** 2 + dy ** 2);
    }
}
// ...

// Reopen the interface.
interface Point {
    distanceFromOrigin(point: Point): number;
}
Point.prototype.distanceFromOrigin = function(point: Point) {
    return this.getDistance({ x: 0, y: 0});
}

μœ„μ—μ„œ μ–ΈκΈ‰ ν•œ 것과 같은 λ¬Έμ œκ°€ μžˆμŠ΅λ‹ˆλ‹€ - getDistance의 철자λ₯Ό 틀리기 쉽고 μ—λŸ¬κ°€ λ°œμƒν•˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€. μ΄λŸ¬ν•œ 이유 λ•Œλ¬Έμ—, TypeScript 에 noImplicitThis μ˜΅μ…˜μ΄ μžˆμŠ΅λ‹ˆλ‹€. 이 μ˜΅μ…˜μ΄ μ„€μ •λ˜λ©΄, TypeScriptλŠ” thisκ°€ λͺ…μ‹œμ  νƒ€μž… 없이 μ‚¬μš©λ  λ•Œ μ—λŸ¬λ₯Ό λ°œμƒμ‹œν‚΅λ‹ˆλ‹€. 해결책은 μΈν„°νŽ˜μ΄μŠ€λ‚˜ ν•¨μˆ˜ μžμ²΄μ—μ„œ λͺ…μ‹œμ  νƒ€μž…μ„ μ „λ‹¬ν•˜κΈ° μœ„ν•΄ this-λ§€κ°œλ³€μˆ˜λ₯Ό μ‚¬μš©ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€:

Point.prototype.distanceFromOrigin = function(this: Point, point: Point) {
    return this.getDistance({ x: 0, y: 0});
}