본문 바로가기

[TypeScript] satisfies operator in Typescript 4.9

by mugglim 2023. 1. 16.

프롤로그

타입스크립트 4.9 버전부터 추가된 satisfies 연산자가 무엇인지 알아봅시다.

타입 단언(Type Declaration)

타입 단언은 변수 명 뒤에 타입을 선언하는 방법입니다. 타입스크립트는 타입 단언보다는 타입 추론이 좋지!! 라고 말할 수 있는데요. 저는 타입 단언과 타입 추론은 상황에 알맞게 사용하는 게 좋다고 생각합니다.

타입 단언 예

그러면, 타입 단언을 언제 사용하나요?

저는 주로 객체의 키와 값의 타입을 고정시키고 싶은 경우에 사용합니다. 예로, 타입스크립트 공식문서 예제를 가져와 보겠습니다. 요구사항은 아래와 같습니다.

  • 디자인 시스템에 사용 될, pallate 객체를 생성해야 합니다.
  • pallate 객체의 키 타입은 red, blue, green 중 하나입니다.
  • pallate 객체의 값 타입은 string, [number, number, number] 중 하나입니다.

우선, 간단하게 pallate 객체를 만들어봅시다.

const pallate = {
    red: '#FF0000',
    blue: '#0000FF',
    green: [0, 128,0]
}

잘 동작하는 것 같습니다. 그런데, 만약 pallate 객체의 키 값에 오타가 발생하면 어떻게 할까요? redrde로 선언하는 것처럼요. 골치 아프네요. 해결하기 위해, 키와 값 타입을 단언해 봅시다.

const pallate: Record<'red' | 'blue' | 'green', string | [number, number, number]> = {
    red: '#FF0000',
    blue: '#0000FF',
    green: [0, 128,0]
}

이제 객체를 선언할 때 키 값을 미리 알고 있으니, 오타와 같은 휴먼 에러를 방지할 수 있습니다. IDE 상에서 자동 완성도 지원하게 되고요! 그런데, 아직도 한 가지 아쉬운 점이 있습니다. pallate 객체를 선언은 잘했지만, 사용하는 부분에서는 우리가 생각한 타입과 다르게 반영됩니다.

const pallate: Record<'red' | 'blue' | 'green', string | [number, number, number]> = {
    red: '#FF0000',
    blue: '#0000FF',
    green: [0, 128,0]
}

// ERROR!
pallate.red.toUpperCase()

pallate.red의 타입은 string이라고 생각하지 않으셨나요? 아쉽게도, pallate.red의 타입은 string 또는 [number, number, number] 중 하나로 평가됩니다. 그래서 pallate.red.toUpperCase구문에서 오류가 발생하게 됩니다. 어지럽네요! 이제 satisfies 연산자를 통해 문제를 해결해 봅시다.

satisfies 연산자

satisfies 연산자는 타입스크립트 4.9 버전부터 사용가능한 문법입니다. (2023-01-16 기준, 최신 버전은 4.9.4입니다.) 사용하는 방법은 as const와 매우 유사합니다. 값 뒤에 satisfies 연산자와 타입을 붙여 주면 됩니다.

돌아와서, 위 예제를 다시 가져와볼게요.

const pallate = {
    red: '#FF0000',
    blue: '#0000FF',
    green: [0, 128,0]
} satisfies Record<'red' | 'blue' | 'green', string | [number, number, number]>

// NOT ERROR!
pallate.red.toUpperCase()

에러가 발생하지 않습니다! satisfies 연산자를 사용하면, pallate을 선언했을 때 타입과 사용할 때 타입을 일치시킬 수 있습니다!

글을 마무리하며

혹시.. satisfies 요놈 as const와 비슷하다고 느끼지 않으셨나요? 저는 비슷한데 크게 2가지가 다르다고 느꼈습니다.

  1. satisfiesas const와 달리, readonly로 만들지 않습니다.
  2. satisfies는 타입을 미리 단언하고 개발하는 경우, 유용할 수 있습니다. (타입 선언부의 타입 === 타입 사용부의 타입)

물론 satisfies가 만능은 아닌 것 같습니다. 언제나 상황에 맞게 선택하는 게 개발자의 몫이고요!

댓글