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 |