๐ TypeScript 4.9 is coming.
Why
์ด๋ค ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋์ง๋ syntax๊ฐ ํ์ํ ๋ฐฐ๊ฒฝ์ ํตํด ์ดํด๋ณด์.
Situation 1.
// ์ฌ๊ธฐ palette๋ผ๋ tuple์ด ์์ต๋๋ค. ๋ ์ฝ๋๋ผ๊ณ ๋ถ๋ฅด์ฃ .
const palette = {
red: [255, 0, 0],
green: "#00ff00",
bleu: [0, 0, 255]
};
// red๋ `number[]` ์ด์ด์ผ ํ๋ค.
const redValue = palette.red.join(',');
// green์ `string` ์ด์ด์ผ ํ๋ค.
const greenValue = palette.green.toUpperCase();
// blue๋ `number[]` ์ด์ด์ผ ํ๋ค.
const blueValue = palette.bleu.join(',');
ํน์ ์ ์ฝ๋์ ๋ฌธ์ ๋ฅผ ๋์น์ฑ์ จ๋์?
bleu
๋ผ๋ ์คํ๊ฐ ์์ต๋๋คโฆ! ใ
ใ
key
๋ก ์ฌ ์ ์๋ ๊ฒ์ด ์ ํด์ ธ์๋ค.- ์ด๋ค ์ ์ฝ์ด ํ์ํ๋ค.
- ํ์ ์ ์?!
(๋น์ฐํ ์ ๊ทผ) palette์ ํ์ ์ด ํ์ํ๊ฒ ๊ตฐ.
type Color = "red" | "green" | "blue";
const palette: Record<Color, string | number[]> = {
red: [255, 0, 0],
green: "#00ff00",
blue: [0, 0, 255], // Gooooood!!
};
์ด๋ ๊ฒ ์คํ๋ฅผ ์ก์ ์ ์์ง! ๋งโฆ
const redValue = palette.red.join(",");
// โ Error: red is `number[] | string`
const greenValue = palette.green.toUpperCase();
// โ Error: green is `number[] | string`
value
์ ๋ํ type infer๊ฐ ์ด๋ ค์์ง๋คโฆ ๐ญ
๋๋ฅ
const palette = {
red: [255, 0, 0],
green: "#00ff00",
blue: [0, 0, 255],
} satisfies Record<Color, string | number[]>;
const redValue = palette.red.join(",");
// โ
red is `number[]`
const greenValue = palette.green.toUpperCase();
// โ
green is `string`
One more thing โ๏ธ
const palette = {
red: [255, 0, 0],
green: "#00ff00",
blue: [0, 0, 255],
} satisfies Record<Color, unknown>; // ๐ we don't need to specific type
const redValue = palette.red.join(","); // `red` is number[]
const greenValue = palette.green.toUpperCase(); // `green` is string
with as const
const palette = {
red: [255, 0, 0],
green: "#00ff00",
blue: [0, 0, 255],
} as const satisfies Record<Color, unknown>; // ๐ we don't need to specific type
const redValue = palette.red.join(","); // `red` is [255, 0, 0]
const greenValue = palette.green.toUpperCase(); // `green` is "#00ff00"
๊ฐ๊ฟ.
Situation 2.
type Animal = {
kind: 'dog' | 'cat';
food: 'fish' | 'meat' | 'chur';
age: number;
}
const puppy = { kind: 'dog', food: 'meat', age: 2 };
function calculateAge(animal: Animal) {
return animal.age;
}
calculateAge(puppy);
// โ `puppy`๋ `Animal` ํ์
๊ณผ ๋ง์ง ์์ต๋๋ค.
// { kind: string; food: string; age: number }
as
โฆ?
calculateAge(puppy as Animal);
๋ํ์ ์ธ ์ํฐํจํด.
puppy๊ฐ ๋ณํด๋ ์ ์๊ฐ ์๋ค.
as const
โฆ?
type Animal = {
kind: 'dog' | 'cat';
food: 'fish' | 'meat' | 'chur';
age: number;
}
const puppy = {
kind: 'dog' as const,
food: 'meat' as const,
age: 2,
};
function calculateAge(animal: Animal) {
return animal.age;
}
calculateAge(puppy);
๋๊ธด ๋๋๋ฐโฆ ๊ท์ฐฎ๋คโฆ
ํ์ ์ ์โฆ?
type Animal = {
kind: 'dog' | 'cat';
food: 'fish' | 'meat' | 'chur';
age: number;
}
const puppy: Animal = {
kind: 'dog',
food: 'meat',
age: 2,
};
function calculateAge(animal: Animal) {
return animal.age;
}
calculateAge(puppy);
๋๊ธด ๋๋๋ฐโฆ
puppy.kind // 'dog' | 'cat'
// not 'dog'
narrowโฆ more narrowโฆ
๋๋ฅ
type Animal = {
kind: 'dog' | 'cat';
food: 'fish' | 'meat' | 'chur';
age: number;
}
const puppy = { kind: 'dog', food: 'meat', age: 2 } satisfies Animal;
function calculateAge(animal: Animal) {
return animal.age;
}
calculateAge(puppy);
typeof puppy.kind // 'dog'
์บฌ
์ ๋ฆฌ
satisfies
๋ผ๋ ์๋ก์ด ๋ฌธ๋ฒ์ด ์๊ฒผ๋๋ฐ,
- Property Name Constraining, Fulfillment ๊ฐ์ฒด์ key๊ฐ์ ์ ํํ ๋, ์ ๋ถ ์กด์ฌํ๋์ง ํ์ ํ ๋ ์ฌ์ฉํ๋ค.
- Infer property value type ๊ฐ์ฒด์ value๊ฐ์ inferํ์ฌ ํ์ ์ผ๋ก ์ง์ ํ ๋, ์ฌ์ฉํ๋ค.
- Safe upcast ํ์ ์ ์์ ํ๊ฒ upcast ์์ผ์ค ๋, ์ฌ์ฉํ๋ค.
TMI
implements
๊ฐ ๋ ๋ปํจ.
References
- ์ง์ ํด๋ณด๊ธฐ
- ์ด ์์ฝ์ด์ ๋ํ ๋ ผ์๊ฐ ์ด๋ค์ง ์ด์๋ณด๋ฌ๊ฐ๊ธฐ https://github.com/microsoft/TypeScript/issues/47920
- ์ถ๊ฐ๋ ๋ค๋ฅธ ๊ธฐ๋ฅ๋ค๋ ๋ณด๋ฌ 4.9 ์๊ฐ ๊ณต์๋ฌธ์ ๊ฐ๊ธฐ Announcing TypeScript 4.9