안녕하세요, 단테입니다.
타입스크립트 4.9의 변경점에 대해 이야기 해보려고 합니다.
TS 4.9 버전은 아래와 같은 업데이트 히스토리를 가지고 있습니다.
4.9 버전에서 추가되는 statisfies operator는 기존 리턴 타입을 제
대로 추론하지 못한 타입 스크립트의 문제점을 해결해주는데요, 한번 살펴보겠습니다.
다음 object literal 변수 palette
를 보세요. blue
를 bleu
로 써버렸네요.
const palette = {
red: [255, 0, 0],
green: "#00ff00",
bleu: [0, 0, 255]
// ^^^ 오타!
};
오타를 방지하고 싶습니다.
type Colors = "red" | "green" | "blue";
type RGB = [red: number, green: number, blue: number];
const palette: Record<Colors, string | RGB> = {
red: [255, 0, 0],
green: "#00ff00",
bleu: [0, 0, 255]
// ~~~~ The typo is now correctly detected
};
하지만 오타를 위해 타입 추론이 아닌 palette
타입을 명시적으로 지정한다면 blue와 red 키 값의 value는 이제 string | RGB
유니온 타입이기 때문에 Array.prototype 이하 api를 사용할 수 없게 되었습니다. string 타입일 경우 Array.prototype.* 메소드를 호출할 수 없기 때문입니다.
statisfies 를 사용할 경우 유니온 타입과 호환되는 타입의 메소드 호출 시도 시 정적 에러를 발생시키지 않습니다. blue
의 오타를 발견함과 동시에 value의 메소드를 사용할 수 있는 것이죠.
const palette = {
red: [255, 0, 0],
green: "#00ff00",
bleu: [0, 0, 255]
// ~~~~ The typo is now caught!
} satisfies Record<Colors, string | RGB>;
// Both of these methods are still accessible!
const greenNormalized = palette.green.toUpperCase();
palette
가 red
, green
, blue
세 가지의 키만 가지게 하려고 하는데요,
// Ensure that we have exactly the keys from 'Colors'.
const favoriteColors = {
"red": "yes",
"green": false,
"blue": "kinda",
"platypus": false
// ~~~~~~~~~~ error - "platypus" was never listed in 'Colors'.
} satisfies Record<Colors, boolean | string>;
// All the information about the 'red', 'green', and 'blue' properties are retained.
const g = favoriteColors.green;
// ^^ g: false
const r = favoriteColors.red;
// ^^ r: string
favoriteColors.green = true;
// ^^ Type 'true' is not assignable to type 'false'.(2322)
위 코드를 한번 찬찬히 살펴보세요. platypus
키 바인딩에 대해 에러 표기를 해주는데요,
변수 g
의 타입을 보면 false
입니다. boolean
이 아니에요.
추후 favoriteColors.green 값에 대해 true 값을 바인딩 하고 싶을 때 favoriteColors.green은 boolean
타입이 아닌 false
타입이기 때문에 에러를 발생시키게 됩니다.
따라서 favoriteColors가 정적 타입 체크에서 freeze object가 아닌 것으로 간주하기 위해서는 다음처럼 해야 합니다.
type Colors = "red" | "green" | "blue";
const favoriteColors = {
"red": "yes" as const,
"green": false,
"blue": "kinda",
} satisfies Record<Colors,unknown>;
// All the information about the 'red', 'green', and 'blue' properties are retained.
const g = favoriteColors.green;
// ^^ g: boolean
const r = favoriteColors.red;
// ^^ r: yes
favoriteColors.green = true;
// ^^ green: boolean
red
키 값에 대해 string 타입이 아닌 "yes" 타입으로 narrow 하게 선언하고 싶다면 as const
를 사용하면 그만입니다.
key 값과 상관 없이 value 값만 정적 체크하고 싶으면 다음 처럼 하면 됩니다.
type RGB = [red: number, green: number, blue: number];
const palette = {
red: [255, 0, 0],
green: "#00ff00",
blue: [0, 0]
// ~~~~~~ error!
} satisfies Record<string, string | RGB>;
// Information about each property is still maintained.
const redComponent = palette.red.at(0);
const greenNormalized = palette.green.toUpperCase();
statisfies operator와 관련된 PR은 아래에서 확인할 수 있습니다.
https://github.com/microsoft/TypeScript/pull/46827
nextjs를 만든 회사 vercel의 member Lee Robinson
은 statisfies operator가 nextjs에 큰 영향을 준다고 말합니다.
GetStaticProps 타입이 어떻게 되어있는지 한번 봅시다.
제너릭 타입 P가 {[key: string]: any}
를 extends
하기 때문에
Page 컴포넌트에서 props를 추론할 때 실제 getStatiProps에서 리턴하는 object의 id 속성을 제대로 추론하지 못합니다.
이를 statisfies operator를 사용해 정확히 props의 타입을 추론할 수 있게 만들 수 있습니다.
오늘은 typescript 4.9 버전 업데이트 내역 중 satisfies operator에 대해 알아봤습니다.
감사합니다.
안녕하세요,
덕분에 satisfies 연산자에 대해서 조금은 이해할 수 있었습니다.
satisfies 연산자가, 정의한 객체 타입(Record)의, 해당하는 value 타입을 반환하고 찾아주는
연산자로 이해했습니다.
위 글 중에서 문의 사항있어 여쭈어 봅니다.
다음과 같은 문장이 있습니다
'변수 g
의 타입을 보면 false
입니다. boolean
이 아니에요.'
혹시 어떤 이유에서 변수 g의 타입이 'boolean'이 아니라 'false' 리터럴 타입 인지
추가 설명 부탁 드릴 수 있을까요,
글에서
변수의 g 타입이
Record<Colors, boolean | string>일 경우
false 타입이고
Record<Colors, unknown>일 경우
boolean 타입으로
변경됩니다.
이렇게 g 타입이 변경되는 이유는 무엇 일까요?
감사합니다
아니 영향까지 ,, 진짜 만족스럽네요 😋