-
TypeScript로 타입을 강화하는 방법: satisfies와 Uppercase<T> 활용하기Javascript 2024. 8. 24. 10:30
TypeScript 4.9에 새롭게 도입된
satisfies
연산자, 여러분은 사용해보셨나요?저는 이 기능을 굉장히 좋아합니다.
satisfies
가 도입된 지 1년 반 정도가 지난 지금, 초기에 예상했던 것보다 훨씬 다양한 곳에서 이 연산자가 유용하다는 것을 체감하게 됩니다.그래서 오늘은 이 기능을 활용한 몇 가지 유용한 예시를 소개하려고 합니다.
satisfies의 기본 개념
이번 글에서는
satisfies
의 기초적인 설명은 생략하고, 실용적인 활용 예시를 중점적으로 다루겠습니다.더 깊이 있는 설명이 필요하신 분들은 아래 블로그 글을 참고 하시면 됩니다.
https://mycodings.fly.dev/blog/2023-07-14-understanding-typescript-satisfies-operator
Uppercase와 함께 타입 강화하기
이번에 소개할 방법은
satisfies
와Uppercase
를 함께 사용하여 기존 타입을 보다 강력하게 만드는 것입니다.예를 들어, COLOR 객체의 키를 대문자로 강제하고 싶을 때가 있을 것입니다.
이를 타입으로 정의하면 다음과 같이 표현할 수 있습니다.
type ColorKey = Uppercase<string>
Uppercase<T>
는 문자열 타입을 받아 그 문자열을 대문자로 변환한 타입을 반환합니다.이와 유사한 기능을 하는 다른 함수들도 존재합니다.
이
ColorKey
타입을 활용하여 "키가 대문자로 제한된 COLOR 객체"를 만들 수 있습니다. 두 가지 방법을 살펴보겠습니다.// 타입 주석 사용 const COLOR_ANNOTATE: Record<ColorKey, string> = { WHITE: "#FFFFFF", BLACK: "#000000", badColor: "#hoge" // 🚫 타입 오류 ("badColor"가 대문자가 아님) } // satisfies 사용 const COLOR_SATISFIES = { WHITE: "#FFFFFF", BLACK: "#000000", badColor: "#hoge" // 🚫 타입 오류 ("badColor"가 대문자가 아님) } satisfies Record<ColorKey, string>
이 두 방법은 겉보기에는 비슷하지만, 중요한 차이가 있습니다.
satisfies
를 사용하는 방법이 더 유리한 이유를 살펴보겠습니다.무엇이 다른가?
COLOR_ANNOTATE
와COLOR_SATISFIES
간의 차이를 살펴보면, "객체의 프로퍼티에 타입 안전하게 접근할 수 있는가"에서 차이가 발생합니다.// 타입 주석 사용 const COLOR_ANNOTATE: Record<ColorKey, string> = { WHITE: "#FFFFFF", BLACK: "#000000", badColor: "#hoge" // 🚫 타입 오류 } // satisfies 사용 const COLOR_SATISFIES = { WHITE: "#FFFFFF", BLACK: "#000000", badColor: "#hoge" // 🚫 타입 오류 } satisfies Record<ColorKey, string> // 타입 안전하게 접근 불가 const selectedColorAnnotate = COLOR_ANNOTATE.???? // 타입 안전하게 접근 가능 const selectedColorSatisfies = COLOR_SATISFIES.BLACK
왜 이런 차이가 발생하는지 조금 더 깊게 알아보겠습니다.
COLOR_ANNOTATE의 타입
COLOR_ANNOTATE
는 타입 주석을 사용하여Record<Uppercase<string>, string>
타입을 가지게 됩니다하지만
Uppercase<string>
은 결국 문자열이므로 최종적으로{[x: string]: string;}
타입이 됩니다.이는 키가 단순히
string
타입이기 때문에 어떤 문자열이든 지정 가능하여 타입 안전성이 떨어집니다.COLOR_SATISFIES의 타입
반면,
COLOR_SATISFIES
는satisfies
를 활용하여 타입 주석을 하지 않았기 때문에 타입 추론에 의해 객체의 실제 타입이 결정됩니다.따라서 다음과 같은 타입을 갖게 됩니다.
{ WHITE: string; BLACK: string; }
실제 값에 기반하여 타입이 추론되므로, 키의 타입이 구체적인 string 리터럴 타입이 되어 각 프로퍼티에 타입 안전하게 접근할 수 있게 됩니다.
다양한 타입과의 조합
Uppercase의 다양한 활용
앞에서
Uppercase<T>
와의 조합 예시를 보았지만, 이 외에도 다음과 같은 타입 함수들이 있습니다.Lowercase<T>
Capitalize<T>
Uncapitalize<T>
이 함수들은 이름 그대로의 역할을 합니다.
이러한 함수들의 자세한 사용법이나
intrinsic
키워드에 대해 더 알고 싶으신 분들은 관련 자료를 찾아보시면 좋겠습니다.TemplateLiteral 타입
위의 타입 함수 외에도
TemplateLiteral
타입과satisfies
를 함께 사용해보는 것도 좋습니다.Uppercase
의 예시처럼 다음과 같이 활용할 수 있습니다.type ErrorMessageKey = `${number}_Error` const ErrorMessage = { "404_Error": "요청하신 페이지를 찾을 수 없습니다", "418_Error": "저는 티포트라서 커피는 좀...", } satisfies Record<ErrorMessageKey, string>
이처럼 다양한 상황에서 활용할 수 있을 것입니다.
마무리
오늘은
satisfies
와Uppercase
를 활용하여 타입을 강화하는 방법을 소개했습니다.이 외에도 제가 좋아하는
satisfies
의 활용법이 몇 가지 더 있으니, 다른 글에서도 소개할 수 있으면 좋겠습니다.앞으로도 다양한 활용법을 공유할 수 있도록 하겠습니다.
감사합니다!
'Javascript' 카테고리의 다른 글
TypeScript의 고급 타입 시스템과 React Hooks 활용법 (0) 2024.08.24 TypeScript로 불필요한 변수 선언 없애기: `satisfies` 활용법 (0) 2024.08.24 NextJS 앱 자체 호스팅: 실제 사례로 알아보는 최적의 방법 (0) 2024.08.09 JavaScript 학습의 어려움과 해결 방법 (0) 2024.08.05 TypeScript 5.6 Beta: 빛의 속도로 타입 검사 가능, 대규모 파일도 문제없어 (0) 2024.08.05