mir.pe (일반/어두운 화면)
최근 수정 시각 : 2024-10-27 00:35:06

TypeScript

타입스크립트에서 넘어옴
프로그래밍 사이트 선정 프로그래밍 언어 순위 목록
{{{#!wiki style="margin: 0 -10px -5px; word-break: keep-all"
{{{#!wiki style="display: inline-table; min-width: 25%; min-height: 2em;"
{{{#!folding [ IEEE Spectrum 2024 ]
{{{#!wiki style="margin: -5px 0"
<rowcolor=#fff> 스펙트럼 부문 상위 10개 프로그래밍 언어 직업 부문 상위 10개 프로그래밍 언어
1 Python 1 SQL
2 Java 2 Python
3 JavaScript 3 Java
4 C++ 4 TypeScript
5 TypeScript 5 SAS
6 SQL 6 JavaScript
7 C# 7 C#
8 Go 8 HTML
9 C 9 Shell
10 HTML 10 C++
}}}
}}}
}}}
[ Stack Overflow 2024 ]
[ TIOBE 2024 ]
||<tablewidth=100%><width=9999><-4><bgcolor=deepskyblue><tablebgcolor=#fff,#222> 2024년 8월 기준 검색어 점유율 상위 20개 프로그래밍 언어 ||
1 Python 11 MATLAB
2 C++ 12 Delphi / Object Pascal
3 C 13 PHP
4 Java 14 Rust
5 C# 15 Ruby
6 JavaScript 16 Swift
7 SQL 17 Assembly language
8 Visual Basic 18 Kotlin
9 Go 19 R
10 Fortran 20 Scratch
{{{#!wiki style="margin: 0 -10px -5px; min-height: calc(1.5em + 5px);"
{{{#!folding [ 21위 ~ 50위 펼치기 · 접기 ]
{{{#!wiki style="margin: -5px -1px -11px"
21 COBOL 36 Scala
22 Classic Visual Basic 37 Transact-SQL
23 LISP 38 PL/SQL
24 Prolog 39 ABAP
25 Perl 40 Solidity
26 (Visual) FoxPro 41 GAMS
27 SAS 42 PowerShell
28 Haskell 43 TypeScript
29 Dart 44 Logo
30 Ada 45 Wolfram
31 D 46 Awk
32 Julia 47 RPG
33 Objective-C 48 ML
34 VBScript 49 Bash
35 Lua 50 Elixir
}}}}}}}}} ||
[ PYPL 2024 ]

}}} ||
프로그래밍 언어 목록 · 분류 · 문법
TypeScript
파일:Typescript_logo_2020.svg
<colbgcolor=#ffffff,#1f2023><colcolor=#3179C7> 개발 Microsoft
출시 2012년 10월 1일
최신 버전 5.6.3 (2024년 10월 9일)
파일 확장자 .ts[1]
파일:홈페이지 아이콘.svg | 파일:X Corp 아이콘(블랙).svg |
1. 개요2. 상세3. 개발 환경 만들기4. 자바스크립트와의 차이5. 사용 사례
5.1. 백엔드와 프론트엔드 통합5.2. 프론트엔드
6. 특장점
6.1. 기존 자바스크립트 소스와의 호환6.2. 다른 언어와의 문법 유사성6.3. IDE와의 궁합6.4. 과감한 신규문법 도입6.5. npm 사용
7. 주의사항
7.1. 결국에는 자바스크립트로 컴파일7.2. 학습 곡선 및 Trade-off7.3. JavaScript 라이브러리의 호환성7.4. 결론
8. 라이브러리9. 관련 문서

[clearfix]

1. 개요


마이크로소프트에서 구현한 JavaScript의 슈퍼셋(Superset) 프로그래밍 언어. 확장자로는 .ts를 사용[2]하며, 컴파일의 결과물로 JavaScript 코드를 출력한다. 최종적으로 런타임에서는 이렇게 출력된 JavaScript 코드를 구동시키게 된다.

2. 상세

TypeScript라는 이름답게 정적 타입을 명시할 수 있다는 것이 순수한 자바스크립트와의 가장 큰 차이점이다. 덕분에 개발 도구( IDE 컴파일러 등)에게 개발자가 의도한 변수나 함수 등의 목적을 더욱 명확하게 전달할 수 있고, 그렇게 전달된 정보를 기반으로 코드 자동 완성이나 잘못된 변수/함수 사용에 대한 에러 알림[3] 같은 풍부한 피드백을 받을 수 있게 되므로 순수 자바스크립트에 비해 어마어마한 생산성 향상을 꾀할 수 있다. 즉, '자바스크립트를 실제로 사용하기 전에 있을만한 타입 에러들을 미리 잡는 것' 이 타입스크립트의 사용 목적이다.

개발자와 도구 간의 상호작용에서 뿐만 아니라 개발자 간의 상호작용에서도 상당한 이점이 있는데, API를 구현하고 사용함에 있어 해당 API의 인풋과 아웃풋이 무엇인지 명확하게 표현할 수 있으므로, API 하나 쓰는데에도 일일이 매뉴얼을 찾아봐야 하거나 심하면 해당 API의 코드까지 뒤적거려봐야 하는 자바스크립트에 비해 효율적이다.

델파이 C#의 개발을 주도한 Anders Hejlsberg가 개발에 참여하고 있다. 이 때문인지 일부 기능이나 문법은 C#와 유사하다.

3. 개발 환경 만들기

가장 대중적인 타입스크립트 개발 환경은 Node.js이다. Node.js를 설치한 다음 터미널에서
npm i -g typescript
를 입력하면 타입스크립트 컴파일러(타입스크립트 → 자바스크립트 변환기)가 설치된다.

만일 Windows의 파워셸에서 오류가 발생했다면 관리자 권한의 파워셸에서
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
를 통해 파워셸에 권한을 주고 입력한다.

Mac/Linux에서 Node.js npm을 사용할 때, 위에서 언급한 Windows 환경에서의 권한 문제와 유사한 권한 문제가 발생할 수 있다. 그런 문제를 미연에 방지하기 위해 nvm을 먼저 설치하고 npm을 사용하기를 권장한다. nvm을 쓰지 않고 Node.js와 npm을 사용하는건 물론 가능하지만 특히 Mac은 sudo를 웬만하면 사용하지 말라고 하는 OS인 만큼, 정말 정말 정말 귀찮은 문제에 많이 얽힐 수 있으니, 정신건강과 보안을 위해 nvm을 꼭! 설치하기 바란다. Windows에서도 nvm-windows라는 비슷한 프로그램이 있으나 위의 nvm과 완전히 별도의 프로젝트임을 감안하고 사용해야 한다.

그 뒤로는 .ts 파일을 타입스크립트를 사용하여 작성하고 터미널이나 명령 프롬프트에서 해당 폴더로 이동하여 'tsc 파일이름(확장자 제외)'를 입력해주면 된다.

예) 파일 이름이 script.ts 일 때,
tsc script
위와 같이 입력하면 script.js 파일이 같은 폴더에 생성된다.
또는 아래와 같은 방법도 있다 :
tsc --init
를 실행한 후, 생성되는 tsconfig.json을 수정하고 아래와 같은 명령어를 사용해도 동일한 결과가 나온다.
tsc

위의 방법들은 타입스크립트를 자바스크립트로 변환하고, 다시 자바스크립트를 실행해야 하는 번거로움이 있는데, ts-node를 사용하면 타입스크립트를 바로 실행할 수 있다.[4]
ts-node 설치:
npm install -g ts-node
typescript 실행:
ts-node 타입스크립트파일명.ts

다양한 IDE들이 타입스크립트를 지원하고 있지만, 역시 타입스크립트의 제작사인 마이크로소프트 Visual Studio Code와의 가장 정합성이 훌륭하다고 평가받고 있다. 위의 커맨드를 내부 터미널에 입력해 컴파일할 수도 있고, 프로젝트 내의 .vscode 폴더에 launch.json및 task.json 설정 파일을 생성해서 본인의 프로젝트에 적합한 설정을 입력해주면 Visual Studio처럼 F5, 혹은 Ctrl + F5 단축키로 컴파일부터 실행까지 일사천리로 진행시킬 수도 있다.

Node.js 22.6.0 버전부터 컴파일 없이도 바로 타입스크립트를 실행할 수 있는 기능이 실험적으로 지원된다.
node --experimental-strip-types 타입스크립트파일명.ts

이는 TypeScript의 타입을 단순히 지워서 실행하는 것이기 때문에 Deno나 ts-node의 실행 기능과는 차이가 있다. 또한 js 확장자로 ts 확장자 모듈을 import 할 수 없고 Deno처럼 ts 확장자를 지정해서 가져와야 한다.

그러나 별도의 외부 런타임을 설치할 필요 없이 Node.js가 즉시 타입스크립트 파일을 실행할 수 있다는 것 만으로도 커다란 편의성 제공이 예상된다.

4. 자바스크립트와의 차이

타입스크립트에서는 버그가 일어나기 쉬운 요소의 타입을 선언하여 버그가 일어나는 것을 막아준다. 가령 자바스크립트에서는 타입이 다른 두 변수를 계산을 시켜주면
#!syntax javascript
const a = 3;
const b = '5';
console.log(a*b)
이게 계산이 작동되어 15를 출력하는 기능이 있다. 만일 프로그래머가 이게 다른 언어처럼 계산이 작동하지 않을 것을 의도하고 이렇게 코드를 지었다면 의도치 않은 작업이 이루어지는 버그가 발생하는 것이다.

타입스크립트에서는
#!syntax typescript
const a:number = 3;
const b:string = '5';
console.log(a*b)
이렇게 숫자면 숫자, 문자열이면 문자열이라고 타입을 선언해주어서 계산이 작동되지 못하게 하거나, 컴파일 전에 오류 메시지를 띄우게 한다.[오류메시지]
var alist = document.querySelectorAll('a');
for (var i = 0; i < alist.length; i++) {
alist[i].style.color = '#333'
};

var example = document.querySelector('.exampleClass');
example.style.backgroundColor = "#ccc";

document.addEventListener('mousemove', function () {
var x = event.clientX;
document.querySelector('h1').style.fontSize = (x / 50) + 'px'
});
}}} const alist = document.querySelectorAll('a');
for (let i: number = 0; i < alist.length; i++) {
alist[i].style.color = '#333'
};

const example: HTMLElement = document.querySelector('.exampleClass');
example.style.backgroundColor = "#ccc";

document.addEventListener('mousemove', function (event: MouseEvent) {
const x = event.clientX;
(document.querySelector('h1') as HTMLElement).style.fontSize = x / 50 + 'px';
});
}}}

5. 사용 사례

5.1. 백엔드와 프론트엔드 통합

타입스크립트는 Node.js 런타임뿐만 아니라 원래 자바스크립트의 고향인 프론트엔드 개발에서도 상당히 유용하다. 특히 프론트엔드와 백엔드[9]를 모두 TypeScript로 구현한다면 종전과는 비교할 수 없을 정도로 높은 개발 안정성과 편의성을 확보할 수 있다. 프론트엔드-백엔드 상호 간 데이터 통신을 위해서는 일반적으로 JSON 형식의 REST API를 구현하게 되는데, [10] 이렇게 사용되는 데이터 포맷은 개발 과정 중에 수없이 변경되고 또 변경되기 마련이다. 이로 인해 프론트엔드와 백엔드 개발자 사이에서는 수도 없이 커뮤니케이션 로스가 발생하고[11] 이는 고스란히 개발자의 피로도 상승 및 개발 기간 증가, 유지보수성의 저하로 이어진다. 게다가 이러한 문제점은 실제로 코드를 동작시키지 전까지는 알아채기 어려운 경우도 많기 때문에 최악의 경우 검증되지 않은 버그가 남은 채 프로젝트를 퍼블리시하게 될 수도 있다. TypeScript가 이러한 사태를 미연에 방지할 수 있는 이유는, 프론트엔드와 백엔드간의 데이터 포맷을 타입으로 정의하여, 이를 양측에서 공통으로 참조하도록 구현하고.[12] 데이터 포맷의 변경 사항이 발생할 경우 이렇게 공용화된 타입의 정의부를 수정함에 따라 프론트엔드와 백엔드 코드에 컴파일 에러를 발생시킴으로써 데이터 포맷의 통일을 강제하기 때문이다.[13]

물론 백엔드 개발자들은, 타입스크립트 사용 이전에 프론트엔드 개발자에게 올바른 API를 제공하고 본인의 정신건강을 지키기 위해서는 Swagger등의 API문서의 작성이 선행되는 게 권장되긴 하겠으나, IDE에서 제공하는 자동 완성이나 API 에러 알림 등의 피드백 덕분에 문서 참조의 필요성을 줄일 수 있다는 것 자체가 상당한 장점이다.

5.2. 프론트엔드

물론 프론트엔드에서도 단독으로 사용이 가능하다. 바닐라 자바스크립트로 컴파일 되는 것은 당연하거니와, Google의 Angular프레임워크는 2.0부터 아예 타입스크립트로만 작성되도록 바뀌었다그 때문에 사용자들이 많이 떨어져나갔지만. Facebook의 리액트는 React.js와 React Native를 가리지 않고 타입스크립트 사용이 가능하다. 현재는 JavaScript와 TypeScript진영간의 교류도 굉장히 활발하고, DefinitelyTyped 등의 기여로부터 React에서 TypeScript를 사용하는 것은 정석 중의 하나로 자리잡았다. React의 경우는 특히나 Function Component, Hooks와 함께 타입스크립트를 사용한다면 이전에 클래스 컴포넌트를 사용할 때보다 훨씬 쉽게 개발이 가능하다.

6. 특장점

6.1. 기존 자바스크립트 소스와의 호환

타입스크립트를 사용할 때, 타입스크립트가 런타임에서 그대로 돌아가는 경우는 드물다. 개요에 서술하였듯 타입스크립트는 컴파일을 통해 자바스크립트로 변환되는 것이 일단 첫번째 목적인데, 그렇기 때문에 기존의 자바스크립트와 함께 사용하는 것이 가능하며, 자바스크립트 런타임은 그 컴파일된 자바스크립트를 기존의 자바스크립트 파일과 실행 가능하게 되는 것이다. 기존의 자바스크립트 프로그래머들은 타입스크립트를 도입할 때, 처음 고려해봐야 할 것이 '*.d.ts' 파일 작성이다. 클래스, 클래스, 또는 어떤 자바스크립트 객체이든지 타입스크립트로 정의 가능한데, 기존의 자바스크립트 소스를 일절 건드리지 않고 *.d.ts 파일 작성만으로 타입스크립트 도입에 큰 도움을 줄 수 있다. DefinitelyTyped 레포지토리에서 다운받는 @types/<패키지이름> 패키지가 그것이다. 이 레포지토리는 기존 자바스크립트 npm 패키지들이 기존 소스를 건드리지 않고 타입스크립트 진영에 자연스럽게 녹아들 수 있도록 도움을 주었다. Javascript 언어 차원에서 지원하는 API들의 입출력 타입들도 친절하게 정의돼 있기 때문에 이를 더 안정적으로 사용할 수 있게 되기도 한다.

또한 타입스크립트는 const, let 같은 es2015 이상의 버전에서 사용되는 구문을 지원하는데, 이걸 컴파일을 시키게 되면 es3 버전으로 컴파일을 시켜줘서 IE 구버전에서도 작동할 수 있게 해준다! 즉, 상위 버전의 자바스크립트 구문을 사용하고도 IE 구버전을 지원할 수 있다.

6.2. 다른 언어와의 문법 유사성

애초에 자바스크립트가 C, C++, 자바나 C#같은 언어들처럼 (), {}, ; 등을 사용하는 C-family언어이기 때문에 문법적으로 유사함을 내세우는 타입스크립트 역시 C-family인데, 그 정도가 특히 더 가까워져서, 예를 들면 Generic에 <> 기호를 쓴다. 타입스크립트가 자바, C#, C++와는 본질적으로 비슷하지도 않지만, 타입스크립트를 처음 입문하는 기존 개발자들은 '어! 저거 제네릭이네!' 라고 빠르게 이해할 수 있을 것이다. 거기에 interface, const 같은 지시문 역시 기존 언어 사용자들이 익숙하다고 느낄만한 사용방법을 갖고 있다.

6.3. IDE와의 궁합

타입 개념의 도입을 통해 TypeScript 개발을 지원하는 IDE로부터 풍부한 피드백을 받을 수 있다. 일반적인 여느 정적 타입 언어들처럼 자동 완성을 지원하거나, 해당 타입이 지원하지 않는 연산[14]의 시도나 잘못된 인자를 사용한 함수 호출 등을 코딩 중에 즉석에서 검출할 수 있는 것은 기본. 심볼의 이름을 변경하면 해당 심볼을 참조하는 모든 코드들을 자동으로 수정해주는 리팩토링 기능 역시 JavaScript가 아닌 TypeScript이기 때문에 지원될 수 있는 기능이다. 대표적인 IDE로는 JetBrains의 WebStorm이 있으며 IntelliJ IDEA도 얼티밋 에디션을 구입하면 웹 개발 기능을 사용할 수 있다.

특히 Microsoft에서 만든 언어답게, 같은 회사에서 만든 Visual Studio Code(이하 VSC)와의 궁합이 엄청나다. IDE는 아니지만, 각종 플러그인을 통해 TypeScript로 상상할 수 있는 모든 개발환경을 너무나 쉽게 구축 가능하다. VSC나 그 플러그인 역시 대부분 TypeScript로 개발되고 있기 때문에 당연하다면 당연한 결과.

6.4. 과감한 신규문법 도입

Node.js를 포함해서 기존 자바스크립트 생태계에는 언어의 버전이 올라가도 어느정도 하위호환성을 위해 빠르게 새로운 문법을 추가하거나 기존 문법을 변경하지 못한다. babel과 같은 트랜스파일러를 통해 ES6+ 문법을 ES5 문법으로 컴파일해서 사용하는등 호환성 문제를 해결하기 위한 여러 노력들은 있었으나, 마음대로 트랜스파일 환경을 구성하는건 쉬운일이 아니고, 자바스크립트 문법이 아무리 급진적으로 발전하고 있다 하더라도 신규문법이 제안되어서 거절되는 경우도 많고, 채용이 결정되더라도 실제로 사용이 가능하는데까지 여러 절차를 거치며 최소 1~2년은 걸린다.

반면 타입스크립트는 마이크로소프트라는 거대 테크기업이 주도적으로 언어의 발전을 돕고 있으며, 어차피 사용하려면 컴파일과정을 거쳐야 하며 이 과정에서 하위호환성을 따지는게 약간 무의미해지기 때문에 제안단계에 있던 유력한 신규문법들을 ECMA 보다도 더 빠르게 채용하고 있다.

ECMA 에서 반려되어 자바스크립트에선 채용될 가능성이 사라진 몇가지 문법들 중에 타입스크립트 개발자들이 보기에 유용하다고 생각된 문법들도 일부 채용했는데 대표적으로 데코레이터와 추상클래스 등이 있다. 이런 문법들은 엔터프라이즈급 프로젝트를 개발해야 할 수록 유용한 것들이었고, 기업에서 프론트엔드 개발 또는 Node.js 기반 백엔드 개발시 타입스크립트 사용을 적극적으로 고려하게 되는 큰 이유가 되었다.

6.5. npm 사용

뿌리가 자바스크립트인만큼 Node.js npm 패키지들을 손쉽게 사용할 수 있으며, 타입스크립트 컴파일러 자체가 npm 패키지이기도 하다. npm install typescript로 설치 가능하다.

7. 주의사항

7.1. 결국에는 자바스크립트로 컴파일

타입스크립트는 결국 자바스크립트로 컴파일되어 동작하므로 '런타임에는 약타입'이라는 약점이 있다. 가령 타입스크립트로 작성한 Node.js 서버가 HTTP 요청을 받았을 때 클라이언트가 `username`이라는 값을 보내주었다고 선언할 수는 있지만, 이는 가정이 맞았을 때 자신의 코드가 잘 동작함을 보장할 뿐이지 사용자가 실제로 어떤 값을 보냈는지 검사하지는 않는다. 이는 타입스크립트 사용 시 반드시 고려해야 할 문제이다.

실행 시점에 자료형을 검사하려면 type guard 함수를 직접 작성하거나, io-ts, runtypes 등의 라이브러리를 사용해 자료형 검사를 부분적으로 자동화할 수 있다. 하지만 언어 차원에서 이를 지원하는 것이 아니므로 결국 사용자가 불편을 감수할 수밖에 없다.

다른 강타입 언어들 또한 대체로 컴파일 시점에 자료형을 확인하지, 실행 시점에는 타입을 검사하지 않는다. 가령 C++ 컴파일러는 형변환이 불가능한 자료형 간의 대입을 금지하지만, 컴파일된 기계어에는 자료형을 검사하는 명령이 없다. 중요한 차이점이라면 다른 강타입 언어는 다른 라이브러리를 사용할 때 컴파일러를 거쳐야 하니 타입 규칙을 지켜야 하지만, 타입스크립트 코드를 컴파일해 나온 자바스크립트 코드를 직접 호출할 경우 컴파일러를 거치지 않으므로 예상치 못한 자료형을 전달하는 걸 막을 수 없다. 따라서 자신의 프로그램이 외부로부터 신뢰할 수 없는 데이터를 받아오는 경계선을 파악하고 필요할 경우 런타임 타입 검사 코드를 추가해야 한다.

7.2. 학습 곡선 및 Trade-off

자바스크립트는 객체가 갖는 속성을 어떻게든 개발자가 파악해서 어떻게든 에러 없이 동작하도록 만능 Object를 통해 설계하는 것이 기본적인 개발 흐름이다. 반면 타입스크립트는 이토록 지나치게 자유로운(=위험한) 변수/객체 활용에 의도적으로 제약을 걸어 개발의 안정성 및 편의성을 증대시키는 것이 그 존재의의임에 유의할 필요가 있다.

특히 복잡한 객체를 안전하게 활용할 수 있도록 제공되는 타입스크립트의 대표적인 도구가 Advanced Type과 Utility Type인데, 이 기능들은 자바스크립트 뿐만이 아니라 다른 언어에서도 생소한 개념[15]이기 때문에 개발자들에게 익숙하지 않을 가능성이 상당히 높다. 모든 개발자가 문서를 한번 보고 응용 가능할 정도가 아니기 때문에, 첫 도입시에 이 부분을 간과하면 오히려 도입 전보다 생산성이 안좋아질 수도 있다는 점에 유의하는 것이 좋다.

또한 위와 같은 도구를 활용해서 기껏 엄밀하게 typing을 해놨더니 업계에서 흔히 있는요구 사항 및 기능 변경, 리팩토링 작업 등으로 인해 기능 구현에 더해 typing까지 덤으로 다시 해야 하는 불상사가 생길 수도 있다. 경우에 따라서는 아예 any 타입[16]로 도배하는 것만도 못한 결과가 초래될 수도 있다는 것. 따라서 적재적소에 타입스크립트의 기능을 도입하는 안목이 필요해질 수 있다.

7.3. JavaScript 라이브러리의 호환성

다른 사람이 만든 라이브러리를 TypeScript에서 쓰려면 해당 라이브러리가 TypeScript로 작성되었거나, 별도로 .d.ts 형식의 타입 정의(type definition) 파일을 제공해야 한다. 간혹 직접 타입 정의를 제공하는 라이브러리도 있지만, 대부분은 DefinitelyTyped라는 공개된 프로젝트를 통해 타입 정의를 제공한다. 이러한 경우 some-js-library 패키지를 설치할 때 @types/some-js-library 패키지를 함께 설치하면 TypeScript에서 사용할 수 있다.

이용자가 많고 유명한 라이브러리들은 대부분 다른 개발자들의 오픈소스 공유(재능기부)를 통해 타입 정의를 제공하고 있지만, 일부 라이브러리의 경우 타입 정의가 없어서 TypeScript에서 사용할 수 없다. 그럼에도 불구하고 반드시 특정 라이브러리를 사용해야 할 경우, 선택지가 두 가지 있다.
  1. //@ts-ignore 주석을 import문 위에 붙여서 컴파일러를 침묵시킨다. 또는 require()를 사용하여 컴파일 오류 없이 라이브러리를 사용할 수는 있다. 물론 이렇게 불러온 라이브러리의 심볼들에 대해서는 타입 검사가 이루어지지 않기 때문에 TypeScript의 장점을 활용하기 어렵다.
  2. 직접 타입 정의 파일을 만든다.답답해서 내가 쓴다 TypeScript 컴파일러는 소스 코드가 있는 디렉토리의 모든 .d.ts 파일을 불러오므로, 다음과 같은 타입 정의 파일을 적당한 곳에 던져놓으면 된다. 물론 규모가 좀 있는 프로젝트를 꾸린다면 타입 정의 파일을 별도의 디렉토리에 모아놓는 것이 편하다.
#!syntax typescript
// some-js-library.d.ts
declare module "some-js-library" {
    function someFunction(a: string, b: number): void;
    class SomeClass {
        /* .... */
    }
}

위와 같이 특정한 패키지(예시에서는 some-js-library)에 대한 타입 정의를 만들면, 자신의 코드에서 import { someFunction } from "some-js-library";와 같은 식으로 불러와서 사용할 수 있다.
혹은 아래와 같이만 해도 에러는 나지 않는다. 하지만 자동완성을 사용할 수는 없다.
#!syntax typescript
// some-js-library.d.ts
declare module 'some-js-library';
자신이 만든 타입 정의를 여러 개의 프로젝트에서 사용한다면 이를 직접 DefinitelyTyped 프로젝트에 제공하여 다른 개발자들과 함께 사용할 수도 있다.

만약 해당 라이브러리의 JsDoc이 충실하다면 요즘 IDE나 편집기는 타입정의 없이 알아서 JsDoc을 해석하여 타입체크와 intelicode를 지원한다.
아래와 같은 JsDoc이 서술된 JavaScript 모듈이 있다고 하자.
#!syntax javascript
// cacoon.js

/**
 * @template {string | number} T
 * @param {string} source
 * @param {T} value
 * @param {(input: T) => number} proc
 * @returns {string}
 */
export function caccoon(source, value, proc) {
  return source.repeat(proc(value));
}

아래와 같이 특별히 TypeDef 파일 없이 TypeScript에서 바로 사용 가능하다(다만 tsconfig.json에서 JavaScript 혼용을 허용해야 한다).
#!syntax typescript
// main.ts
import { caccoon } from "./cacoon";

const values = ["one", "two", "three", "four", "five"] as const;

function alter(input: (typeof values)[number]) {
  return values.indexOf(input) + 1;
}

for (const value of values) {
  const result = caccoon("token", value, alter);
  console.log(result);
}
파일:vscode-jsdoc-ts.png
VSCode의 JsDoc intelicode
Visual Studio Code에서 보기와 같이 Import, intelicode(자동완성)가 잘 된다.

7.4. 결론

위와 같은 단점과 더불어 JavaScript 자체의 사양이 업그레이드되며 TypeScript만의 기능들이 도입되고, JsDoc의 발전으로 JavaScript만으로도 충분한 Type 지원이 가능해져 여러 프로젝트가 TypeScript 지원을 포기하고 JavaScript의 JsDoc으로 완전히 대체하는 걸 고려하거나 실제 대체하고 있다. TypeScript의 type은 any type 남용과 런타임 타입 체크가 없다는 점, 형의 자유도가 JavaScript의 가장 큰 장점인데 이를 망친다는 주장[17] 등 여러 방면에서 타입스크립트는 유명무실하다는 비판이 있으며, JavaScript + JsDoc은 컴파일이 필요하지 않다는 아주 큰 장점이 있어서 TypeScript의 필요성에 의심이 점점 강하게 제기되고 있다[18]. 실제로 2023년 가을에는 루비 온 레일즈의 개발자가 주도하는 "터보 8"이라는프레임웍에서 타입스크립트 코드가 퇴출돼서 큰 화제가 되었다. 더우기, 스벨트라는 프레임웍에서도 타입체크를 ts에서 JsDoc으로 이전시켜 버렸다. 기존 코드를 싹 다 갈아엎을 수는 없다보니 타입스크립트가 계속 쓰이기는 하는데, 타입 체킹은 다른 라이브러리로 넘겨버린 것이다.

TypeScript의 장점이 단점을 능가하지 않는 개발환경 하에서는 JsDoc을 고려해보는 것도 좋다. 만약 프로젝트 곳곳에서 형변환이나 any type 남발로 불필요한 개발 시간, 인력이 소모된다면 해당 프로젝트가 정말 TypeScript를 요구하는지 다시 검토해볼 필요가 있다.[19]

다만 위 단점들 전부 TypeScript가 주류언어로 떠오르고, JavaScript가 발전하고, 각종 편집기의 intelicode가 강화되면서 발견된 점들이고 어디까지나 TypeScript가 모든 JavaScript 프로젝트와 맞지는 않다는 뜻이다[20]. 정말 문제투성이 언어였으면 어느 정도라도 인기를 얻은 언어가 되지 못한다.

반대로 JsDoc등의 meta information 없이 언어가 자체적으로 타입을 지원한다는 건 분명 큰 장점이므로(대부분의 버그는 프로그래머의 실수이고, 타입 강제는 이런 실수를 줄일 수 있는 가장 강력한 방법이다) 아예 TypeScript 사용을 강제하는 프레임워크나, TypeScript를 컴파일 없이 바로 돌리는 가상 머신도 등장하고 있다[21].

게다가 타입 선언과 체크는 타입스크립트라는 이름에서 알 수 있듯이 타입스크립트의 요체인데, 자바스크립트의 표준규격이라 할 수 있는 ECMAscript에서도 type annotation 이 제안되고 있는 상황이다. ECMAscript 측에서 애노테이션을 규범으로 받아들인다면 사실상 자바스크립트를 타입스크립트처럼 코딩하는 것이 권장되는 환경이 된다.

8. 라이브러리

9. 관련 문서



[1] AssemblyScript와 같다. [2] 일반적으로 .ts를 사용한다는 의미일 뿐이고 이 확장자명이 절대적이지는 않다. 가령 리액트를 활용해 TypeScript로 프로그램을 작성할 때는 .tsx라는 확장자명이 사용된다. [3] 가령 숫자가 들어와야 할 곳에 문자가 들어온다면 자바스크립트는 그 코드를 아무 의심없이 실행해서 런타임에서 알 수 없는 동작을 한다. 어떻게든 동작 자체는 하기 때문에 이러한 버그를 디버깅하는 건 매우 귀찮은 일인데, 타입스크립트는 이런 코드에 대해서는 컴파일타임에 에러를 발생시켜 개발자에게 알려주므로 개발자가 자신의 실수를 쉽게 파악할 수 있다. 보통의 경우, 명시적으로 명령을 넣어 컴파일하기도 전에 잘못된 부분에 시뻘건 밑줄을 쫙쫙 쳐서 애초에 컴파일 자체가 불가능하게 만든다. [4] 물론 내부적으로는 자바스크립트로 변환한 후에 실행되는 것이다. [오류메시지] "The right-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.; 수리 연산의 우항 타입은 'any', 'number', 'bigint' 혹은 열거형이어야 합니다." [6] 타입스크립트와 최신 자바스크립트를 이제 막 시작하는 초보 개발자들을 위해 조언하자면, 아래 소스코드에 있는 것과 같은 var 지시어와 let 지시어는 첫 학습에만 익히고 var는 아예 사용하지 말고 let은 반복문 같이 꼭 필요한 곳을 제외하고 사용하지 않는 편이 좋다. 언제, 어떻게 변수가 변하는지, 그리고 언제 그 변수를 다시는 사용하지 않게 되는지, 언제 어떻게 변수가 필요없어지는지 명확하게 제시하기 위해서는 const, 상수 지시어만 사용하는 편이 훨씬 좋기 때문이다. const는 '{}으로 둘러싸인 곳 안에서 변하지 않는 상수'의 개념이다. 또한 const로 상수를 선언했을 때에는 굳이 타입을 선언할 필요가 없는 경우가 많은데 다른 값을 대입할 일이 없기 때문이다. 아래 예시처럼 const에 타입을 굳이 선언하는 경우는 컴파일러가 타입추론에 실패해서 하는 경우 등이다. [7] 또한 아래 예시에서처럼 as로 Casting을 해주는 경우도 좋은 사례이지만, 애초에 저런 Casting없이 컴파일러의 타입추론만으로 함수나 변수, 클래스를 사용할 수 있게끔 타입을 정의하는 것이 더 중요하다. 그런 타입정의에 시간이 오래 걸리는 것 같아도 결국에는 시간을 몇십배 절약할 수 있다. [8] tsc에서 옵션을 정해주지 않으면 TypeScript는 JavaScript ES5로 변환되기 때문에 const나 let이 var로 바뀐다. [9] Express 프레임워크 등. [10] XML을 쓰는 경우도 있지만, 로직 개발을 JavaScript 혹은 그 파생 언어로 진행하면서 굳이 XML을 사용해야 할 이유는 거의 없다. 원래부터 JSON 형식을 갖춘 JavaScript 객체를 굳이 XML로 직렬화하거나 반대로 XML을 JavaScript 객체 형식으로 파싱해야만 하는 번거로움을 겪어야 하기 때문. [11] 심지어 프론트엔드와 백엔드를 같은 사람이 개발해도 한쪽에 변경 사항이 있다는 걸 까먹고 반대쪽에 이를 반영하지 않는 케이스가 결코 드물지 않다. [12] 프로젝트 소스 코드 내부에 별도 폴더를 만들어 데이터 포맷용 타입을 정의한 코드를 모아둘 수도 있고, npm 패키지 등의 라이브러리로 구현할 수도 있다. [13] 가령 User라는 타입의 id라는 필드를 name으로 수정한다고 할 때, 기존의 user.id를 참조하고 있던 프론트엔드와 백엔드의 코드들은 컴파일 에러를 발생시키고 개발자는 데이터 포맷의 변경에 따라 어떤 코드들이 수정되어야 하는지를 쉽게 파악할 수 있다. IDE의 리팩토링 기능을 활용하면 연관된 모든 코드들을 자동 수정해주기까지 하므로 일일이 고칠 필요조차 없는 경지에 이른다. [14] 가령 number 타입으로 선언된 배열에 string을 삽입하는 등. [15] 굳이 억지로 비교하자면 Java C# 등 언어의 reflection 개념과 겹치는 부분이 있긴 하겠지만, 애초에 reflection 자체도 자유자재로 활용할 수 있는 개발자가 흔치 않다. [16] 말 그대로 이 변수나 상수를 어떤 타입으로써 활용하든 신경쓰지 않겠다는 의미의 타입으로써, 이 타입으로 변수를 선언하면 컴파일러가 변수의 속성을 파악할 수 없으므로 자바스크립트와 동일하게 어떻게든 개발자가 파악해서 어떻게든 에러 없이 동작하도록 만들어야 한다. 즉 이걸 남용하면 코드 전체가 자바스크립트와 다를 게 없어진다.흑마법 [17] 물론 이것이 단점이기도 하기 때문에 TypeScript라는 것이 등장한 것이기도 하다. JavaScript 뿐만 아니라 Python 역시 3.5 이후로는 type annotation이 권장되는 것을 생각해본다면 동적 특성은 일장일단이 있는 요소이며, 언어 불문하고 단점에 가깝다는 인식이 더 크다는 의미기도 하다. [18] 다만 JsDoc의 타입 체커 또한 내부적으로는 TypeScript에 의존하고 있기 때문에 결국 TypeScript를 간접적으로나마 쓰는 것은 마찬가지다. [19] 물론 이것은 레거시 코드 자체부터 오류가 날 여지가 큰 방향으로 구현돼있다는 의미이기도 하므로 TypeScript 도입 이전에 대대적인 리팩토링부터 먼저 수행해야 하는 상황이지만. [20] 즉, TypeScript가 맞지 않는 프로젝트에 TypeScript를 남용했다 보면 된다. [21] 다만 대부분 내부적으로 JavaScript로 트랜스파일링 하는 형태로 구현한다 [22] 자바의 어노테이션과 비슷하다. [23] 그러나 프론트엔드에서도 얼마든지 사용할 수 있으며 공식문서에도 이에 대한 설명이 존재한다.