TypeScript가 5.0으로 큰 변화를 맞이 했습니다. 이번 주요 변경사항은 Decorator, 파라미터 const 타입, Enum을 Union 타입과 호환 등 여러가지 큰 변화를 맞이 했는데 주요 변경점을 살펴보겠습니다.
Decorator
Nest.js를 사용하신 분이라면 아주 익숙한 문법이 보일겁니다. 바로 Decorator 기능인데요, 해당 기능은 지금까지 실험적(experimental) 기능이었습니다. 이번 5.0으로 올라오면서 실험적 기능이 해제되었고, 구현 방법 자체가 변경되었습니다. 이에 따라 기존 실험적 기능으로 구현된 Decorator는 호환이 불가능해졌습니다. 다행히도 기존 실험적 기능은 여전히 사용가능하도록 조치를 취해줬다고합니다. (Nest.js 팀은 현재 모든 Decorator를 재작성중이며, 당분간은 실험적 기능 옵션 —experimentalDecorators 를 켜서 사용할 것을 권고한 상태입니다.)
이번 변경된 구현법은 TC39에서 제안된 내용으로 변경되었고, 해당 제안은 스테이지 3에 해당하고 있어 추가적으로 큰 변경 사항 없이 적용될 가능성이 큽니다. 이 때문에 Microsoft는 TypeScript 5.0으로 올리면서 해당 내용을 공식 기능으로 변경된것으로 보입니다.
공식 지원으로 확인된 Decorator의 사용처는 classmethodgettersetterfieldaccessor 으로 총 6개입니다. 이 외의 실험적 기능에서 지원했던 사용처인 parameter 에 대한 지원이 삭제되었으며, 실험적 기능으로 지원되던 Decorator와는 완전히 다른 호환성을 지니게됩니다.
새로운 Decorator 기능을 보여주는 예제
Decorator 타입 지원
위에서 설명했다 싶이 실험적 기능이었던 Decorator 기능은 타입이 제대로 지원되지 않았습니다. 이로 인해 Decorator를 작성할 때는 항상 any 혹은 unknown 으로 만들어진 구현체를 사용해야 했고, TypeScript가 아닌 JavaScript에서 사용하던 방식처럼 직접 변수에 대해 validation을 맞춰서 사용해야하는 불편함이 있었습니다. 이번 5.0에서는 관련 타입 추가, decorator 사용시 타입 확인이 추가되어 보다 안전한 타입 사용이 가능해졌습니다.
새로운 Decorator를 타입까지 써서 확인하는 예제
const 파라미터
as const 는 타입스크립트를 사용한다면, 상수를 선언할 때 아주 유용한 방식으로 알고계실 겁니다. 해당 방식은 아주 유용하지만, 어디까지나 상수를 선언할 때만 가능하므로 제한적인 유용함이었습니다. 이번 5.0에서 추가된 const 파라미터를 사용함으로 파라미터가 상수임을 단언 할 수 있게 되었으며, 함수 안에서 파라미터가 바뀌지 않는 다는 것을 타입 상으로 만들어 줄 수 있게 되었고, string, number 등 해당 값의 정확한 타입으로 다룰 수 있게 되었습니다.
const 파라미터 예제
tsconfig에서 여러개의 설정 확장 가능
tsconfig의 extends 옵션이 배열을 받을 수 있도록 변경되었습니다. tsconfig는 여러 프로젝트를 다룰때 기반이 되는 설정을 base로 만들어 각 프로젝트마다 설정을 다르게 주는 것이 가능했습니다. 하지만, @tsconfig 패키지와 같이 외부 base 설정을 기반으로 프로젝트의 설정을 가져오는건 불가능 했는데, 이번 5.0에서는 여러개의 base 설정을 받을 수 있게 추가되면서 이와 같은 문제를 해결 할 수 있게 되었습니다.
tsconfig.json의 extends를 여러개 사용하는 예제
모든 enum 은 Union enum 입니다.
TypeScript 2.0에서 추가된 enum 리터럴 타입은 좀 특별합니다. 각각의 enum의 멤버는 고유의 타입을 갖게되었으며, enum의 타입은 각각의 멤버 타입으로 전환이 가능해졌습니다. 하지만 다음과 같은 문제가 발생하며 enum 사용에 문제를 야기시켰습니다.
Union enum을 보여주는 예제
본 예문은 업데이트 포스팅 글에서 나온 예제이며, c === Color.Red 에서 c === Color.Green 으로 넘어갈때 타입이 오류가 난다는 것을 표현하기 위해 || 대신 && 를 사용했습니다.
기존 방식대로 라면 isPrimaryColor 의 c 의 타입은 number 처럼 작동되어 123 같은 enum이외의 숫자를 사용하는 것이 가능했습니다. (실제 타입 결과는 Color 로 정상 작동하는 것처럼 보였습니다.) 이 문제를 해결하기 위해 TypeScript 5.0에서는 enum의 작동 방식은 각각의 멤버의 실제 값으로 변수 c 를 추론을 하게 되면서, 각각의 고유의 타입으로 추론하게 됩니다. 하지만 다음과 같이 함수를 호출해 값을 초기화하는 경우는 타입을 계산할 수 없습니다.
Union enum을 계산할 수 없는 예제
moduleResolution의 bundler 옵션
최신 번들러에서 지원하던 commonjs, module js의 import 규칙을 지원하게 됩니다. 이에 따라 여러가지 옵션이 더 추가 되었으며 그 중 자주 사용하실 법한 옵션을 소개해봅니다.
allowArbitraryExtensions
위 bundler 옵션처럼 hybrid 방식의 모듈에서 사용할 수 있는 --allowArbitraryExteions 옵션은 css, json 파일 등 JavaScript, TypeScript가 알 수 없는 파일 확장자에 대한 타입 선언 파일(.d.ts)을 찾도록 하는 옵션이 추가되었습니다. 타입 선언 파일의 이름 규칙은 {file basename}.d.{extension}.ts 입니다.
css 파일의 타입 선언 파일을 만드는 예제
JSDoc에 추가된 태그
@satisfies 지원
TypeScript 4.9에서 처음 소개된 satisfies 키워드는 매우 유용합니다. 변수의 타입을 as const 로 단언 하는 것보다 기존에 선언된 타입을 기준으로 단언하는게 훨씬 유용하고, 타입오류를 방지할 수 있기 때문입니다. 이런 유용한 키워드가 TypeScript 5.0의 JSDoc에서 @satisfies 라는 태그로 지원하기 시작합니다.
JSDoc으로 tsc 컴파일러 옵션 타입을 선언, @satisfies로 타입을 확인하는 예제
@overload 지원
함수 오버로드는 꽤 자주 사용하는 함수 선언 방식입니다. JSDoc에서는 해당 방식을 표현할 방법이 없었으나, 이번에 @overload 태그가 추가됨으로 표현할 방법이 생겼습니다.
JSDoc으로 선언된 타입과 다르므로 VSCode에서는 에러가 나오게됩니다.
Import 정렬 옵션 추가
VSCode와 같은 에디터에서 organize import 를 이용해 import 문을 정렬하는게 가능합니다. 하지만, 다음 예제와 같이 대소문자를 구분하는 정렬 때문에 비선호하게 되어 다양한 IDE를 사용하는 팀이라면 해당 기능을 사용하지 못하는 문제가 있습니다.
import 정렬 문제
이에 따라 최신 VSCode에서는 다음과 같은 옵션을 지원함으로, 정렬에 대한 세부적인 옵션을 설정 할 수 있게 되었습니다. 하지만 이 옵션들은 모두 불안정(unstable)한 기능들이라는 점을 아셔야합니다.
VSCode에 추가된 import 정렬 옵션들
속도, 메모리, 패키지 사이즈 최적화
이번 타입스크립트 5.0은 각종 최적화를 이뤄냈습니다. 기존 4.9 대비 tsc의 시작시간이 87%로 줄어 들어 약 13%정도의 성능 개선이 이뤄졌습니다. 컴파일 타임, 패키지 사이즈 등 다양하게 줄어들었으며, 관련된 내용은 Microsoft의 TypeScript 5.0 게시글에 포함된 다음 표를 참고하시면 됩니다.
마무리
이번 신규 기능은 JavaScript의 최신 사양을 따라가려는 움직임이 많고, 구버전의 레거시를 개선하거나, tsc의 최적화가 이뤄지는 등 많은 변화점이 있어 실무 프로젝트에서도 유의미한 변화점을 맞게되는 버전입니다. 덕분에 보다 안정적이고 빠른 개발이 이뤄진다는게 저에겐 즐거운 일입니다.