Typescript

추가적인 타입 검사에는 satisfies 연산자를 사용하자

비숑주인 2025. 4. 3. 10:38

satisfies 연산자의 개념

satisfies 연산자는 객체 리터럴을 선언할 때, 타입 추론된 결과를 그대로 활용하면서 추가적인 타입 검사를 수행할 수 있도록 도와준다. 즉, 변수의 타입을 명시적으로 지정하지 않고도, 객체 리터럴의 각 속성이 원하는 타입을 만족하는지 검사할 수 있다.

 

기본 사용법과 문제 상황

예를 들어, 아래와 같이 객체 리터럴을 선언할 때, 의도한 속성 중 하나에 오타가 발생한 경우를 생각해보자.

const universe = {
  sun: "star",
  sriius: "star", // sirius 오타
  earth: { type: "planet", parent: "sun" },
};

 

여기서 속성 키의 타입은 'sun' | 'sirius' | 'earth'여야 한다. 그런데 위와 같이 선언하면 타입 추론 결과는 각각 sun: string, sriius: string, earth: { type: string, parent: string }가 된다. 이때 인덱스 시그니처를 사용하여 아래와 같이 타입을 지정하면 오타를 잡을 수 있다.

const universe: {
  [key in 'sun' | 'sirius' | 'earth']: { type: string, parent: string } | string;
} = {
  sun: "star",
  sriius: "star", // sirius 오타
  earth: { type: "planet", parent: "sun" },
};

 

이 경우, 타입 에러가 발생하면서 'sriius'가 허용되지 않는 속성임을 알려준다. 하지만 이 방식은 객체 리터럴을 선언할 때 타입 추론의 이점을 잃게 되는 단점이 있다.

 

satisfies 연산자를 활용한 타입 검사

satisfies 연산자는 객체 리터럴 뒤에 satisfies 키워드를 사용하여, 타입 추론된 결과를 그대로 유지하면서도 추가적인 타입 검사를 수행할 수 있게 한다.

const universe = {
  sun: "star",
  sriius: "star", // sirius 오타가 있음
  earth: { type: "planet", parent: "sun" },
} satisfies {
  [key in 'sun' | 'sirius' | 'earth']: { type: string, parent: string } | string;
};

 

위 코드에서 universe 객체의 타입은 타입 추론된 결과를 그대로 사용한다. 단, satisfies 뒤에 명시된 타입을 기준으로 각각의 속성이 검사된다. 이 과정에서 'sriius'라는 잘못된 속성 키가 발견되어 에러가 발생한다. 따라서 오타를 수정하여 올바른 키인 'sirius'를 사용해야 한다.

 

satisfies 연산자의 장점

  • 타입 추론 유지: 객체 리터럴의 선언 시점에 타입 추론 결과를 그대로 사용하므로, 불필요하게 타입을 재작성할 필요가 없다.
  • 추가 타입 검사: 원하는 타입을 satisfies 뒤에 지정함으로써, 선언된 객체 리터럴이 해당 타입을 만족하는지 추가로 검사할 수 있다.
  • 오타 및 실수 방지: 잘못된 속성 키나 타입 미스매치 등의 오류를 컴파일 타임에 미리 잡아내어, 런타임 오류를 방지할 수 있다.

예를 들어, universe 객체의 경우 satisfies 연산자를 사용한 덕분에 'sriius' 오타가 컴파일 타임에 바로 발견된다. 이를 통해 객체의 속성이 올바른지 검증할 수 있으며, 이후 객체를 사용할 때에도 안전하게 사용할 수 있다.

 

satisfies 연산자는 타입 추론의 이점을 유지하면서도 추가적인 타입 검사를 수행할 수 있게 해준다. 객체 리터럴의 선언 시, 의도치 않은 오타나 타입 미스매치로 인한 오류를 미리 잡아내어 코드의 안정성을 높일 수 있게 해주기 때문이다. 따라서 타입스크립트 4.9 이상에서는 복잡한 객체의 타입을 정의할 때 적극적으로 활용하자.