2024๋ 1์ 24์ผ ํ์ ์คํฌ๋ฆฝํธ 5.4 ๋ฒ ํ ๋ฒ์ ๋ฐํ๊ฐ ์์๋ค.
์ด ํฌ์คํ ์ ํด๋น ๋ธ๋ก๊ทธ๋ฅผ ๋ณด๊ณ ๊ณต๋ถํ๊ณ ์ ํํ๊ณ ์ ํจ๊ป ๋ฒ์ญํ๋ฉฐ ์ฎ๊ธด ๊ธ์ด๋ค. (โป์ค์ญ ์ฃผ์)
์ฐ์ TypeScript 5.4 beta ๋ฒ์ ์ ์๋์ ๋ช ๋ น์ด๋ฅผ ํตํด ๋ค์ด๋ฐ์ ์ ์๋ค๊ณ ํ๋ค.
npm install -D typescript@beta
TypeScript 5.4์ ์๋ก์ด ๊ธฐ๋ฅ์ ๊ฐ๋ตํ๊ฒ ์๊ฐํ๋ฉด ์๋์ ๊ฐ๋ค.
1. Preserved Narrowing in Clousures Following Last Assignments
๋ง์ง๋ง ํ ๋น ํ ํด๋ก์ ธ์์ ๋ฒ์๊ฐ ์ข์์ง๋๋ก ํ์ ์ ์ ์ง(๋ณด์กด)ํ๋ค.
2. NoInfer Utility Type
NoInfer ์ ํธ๋ฆฌํฐ ํ์
3. Object.groupBy and Map.groupBy
Object.gruopBy ์ Map.groupBy
4. Support for require() calls in --moduleResolution bundler and --module preserve
--moduleResolution bundler ์ --module preserve์์ require() ํธ์ถ ์ง์.
5. Checked Import Attributes and Assertions
Import ์ attributes ๋ฐ assertions ํ์ธ
6. Quick Fix for Adding Missing Parameters
๋๋ฝ๋ ๋งค๊ฐ๋ณ์ ์ถ๊ฐ๋ฅผ ์ํ ๋น ๋ฅธ ์์ .
7. Upcoming 5.5 Deprecations
ํฅํ 5.5 ๋ฒ์ ์ ์ํ ์ค๋น.
8. Breaking Changes
๋ณ๊ฒฝ์ ๋ฟ์๊ธฐ
์ด์ค์ ๊ฐ์ฅ ์ธ์๊น์๋ 1,2๋ฒ์ ๋ํด ์์ธํ ์์๋ณด๋ ค๊ณ ํ๋ค.
Preserved Narrowing in Closures Following Last Assignments
TypeScript๋ ์ผ๋ฐ์ ์ผ๋ก ์ํํ ์ ์๋ ๊ฒ์ฌ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ณ์์ ๋ํ ๋ณด๋ค ๊ตฌ์ฒด์ ์ธ ์ ํ์ ์์๋ผ ์ ์๋ค. ์ด๋ฐ ๊ณผ์ ์ narrowing์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค.
function uppercaseStrings(x: string | number) {
if (typeof x === "string") {
// TypeScript knows 'x' is a 'string' here.
return x.toUpperCase();
}
}
์์๊ฐ์ ์์์ ํ ๊ฐ์ง ๊ณตํต์ ์ธ ๋ฌธ์ ์ ์ ์ด๋ฐ ์ข์์ง ์ ํ์ด ํจ์์ ํด๋ก์ ธ ๋ด์์ ํญ์ ์ ์ง๋์ง๋ ์๋๋ค๋ ๊ฒ์ด๋ค.
function getUrls(url: string | URL, names: string[]) {
if (typeof url === "string") {
url = new URL(url);
}
return names.map(name => {
url.searchParams.set("name", name)
// ~~~~~~~~~~~~
// error!
// Property 'searchParams' does not exist on type 'string | URL'.
return url.toString();
});
}
์ฌ๊ธฐ์ TypeScript๋ url์ด ๋ค๋ฅธ ๊ณณ์์ ๋ณํ๋์๊ธฐ ๋๋ฌธ์ ์ค์ ๋ก ์ฐ๋ฆฌ์ ์ฝ๋ฐฑ ํจ์์์ URL ๊ฐ์ฒด๋ผ๊ณ ๊ฐ์ ํ๋ ๊ฒ์ด "์์ "ํ์ง ์๋ค๊ณ ํ๋จํ๋ค. ๊ทธ๋ฌ๋ ์ด ๊ฒฝ์ฐ์๋ ํญ์ url์ ๋ํ ํ ๋น ํ์ ํ์ดํ ํจ์๊ฐ ์์ฑ๋๋ฉฐ url์ ๋ํ ๋ง์ง๋ง ํ ๋น์ด๊ธฐ๋ ํ๋ค.
TypeScript 5.4๋ ์ด ์ด์ ์ ํ์ฉํ์ฌ ๋ฒ์๋ฅผ ์กฐ๊ธ ๋ ํ๋ช
ํ๊ฒ ์ขํ๋ค. ๋งค๊ฐ๋ณ์์ let ๋ณ์๊ฐ ๋น์น๊ฐ ํจ์์ ์ฌ์ฉ๋๋ฉด, ํ์
์ฒด์ปค๋ ๋ง์ง๋ง ํ ๋น ์ง์ ์ ์ฐพ์ ๊ฒ์ด๋ค. ๋ง์ฝ ๋ฐ๊ฒฌ๋๋ฉด, TypeScript๋ ํฌํจ ํจ์์ ์ธ๋ถ๋ก๋ถํฐ ์์ ํ๊ฒ ๋ฒ์๋ฅผ ์ขํ ์ ์๋ค.
์ค์ฒฉ๋ ํจ์์ ์ด๋ ๊ณณ์๋ ๋ณ์๊ฐ ํ ๋น๋์ด ์์ผ๋ฉด ์ข์ ํด์์ด ์์๋์ง ์๋๋ค. ํจ์๊ฐ ๋์ค์ ํธ์ถ๋ ์ง ํ์คํ ์ ์ ์๋ ๋ฐฉ๋ฒ์ด ์๊ธฐ ๋๋ฌธ์ด๋ค.
function printValueLater(value: string | undefined) {
if (value === undefined) {
value = "missing!";
}
setTimeout(() => {
// Modifying 'value', even in a way that shouldn't affect
// its type, will invalidate type refinements in closures.
value = value;
}, 500);
setTimeout(() => {
console.log(value.toUpperCase());
// ~~~~~
// error! 'value' is possibly 'undefined'.
}, 1000);
}
์ด๊ฒ์ ๋ง์ ์ ํ์ ์ธ JavaScript ์ฝ๋๋ฅผ ํํํ๊ธฐ ์ฝ๊ฒ ๋ง๋ค ๊ฒ์ด๋ค. ๊นํ๋ธ์์ ๊ทธ ๋ณํ์ ๋ํด ๋ ๋ง์ด ์ฝ์ ์ ์๋ค.
The NoInfer Utility Type
์ผ๋ฐ ํจ์๋ฅผ ํธ์ถํ ๋, TypeScript๋ ๋น์ ์ด ์ ๋ฌํ๋ ๋ชจ๋ ๊ฒ์์ ํ์ ์ธ์๋ฅผ ์ถ๋ก ํ ์ ์๋ค.
function doSomething<T>(arg: T) {
// ...
}
// We can explicitly say that 'T' should be 'string'.
doSomething<string>("hello!");
// We can also just let the type of 'T' get inferred.
doSomething("hello!");
๊ทธ๋ฌ๋ ํ ๊ฐ์ง ๋ฌธ์ ๋ ์ถ๋ก ํ๋ "์ต์์" ํ์ ์ด ๋ฌด์์ธ์ง ํญ์ ๋ช ํํ์ง ์๋ค๋ ๊ฒ์ด๋ค. ์ด๋ก ์ธํด TypeScript๊ฐ ์ ํจํ ํธ์ถ์ ๊ฑฐ๋ถํ๊ฑฐ๋, ์์ฌ์ค๋ฌ์ด ํธ์ถ์ ์๋ฝํ๊ฑฐ๋, ๋ฒ๊ทธ๋ฅผ ๋ฐ๊ฒฌํ์ ๋ ๋ ์ฌ๊ฐํ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ๋ณด๊ณ ํ ์ ์๋ค.
์๋ฅผ ๋ค์ด ๋ค์๊ณผ ๊ฐ์ด, defaultColor(์ ํ์ ๋งค๊ฐ๋ณ์)์ ํจ๊ป colors(์์ ์ด๋ฆ)๋ชฉ๋ก์ ๊ฐ์ ธ์ค๋ CreateStreetLight ํจ์๋ฅผ ์์ํด ๋ณด์.
function createStreetLight<C extends string>(colors: C[], defaultColor?: C) {
// ...
}
createStreetLight(["red", "yellow", "green"], "red");
์๋ colors ๋ฐฐ์ด(C[])์ ์๋ defaultColor๋ฅผ ์ ๋ฌํ๋ฉด ์ด๋ป๊ฒ ๋ ๊น? ์ด ๊ธฐ๋ฅ์์ ์์์ "์ง์ค์ ๊ทผ์(source of truth)"์ด ๋์ด์ผ ํ๊ณ defaultColor๋ก ์ ๋ฌํ ์ ์๋ ๋ด์ฉ์ ์ค๋ช ํ๋ค.
// Oops! This undesirable, but is allowed!
createStreetLight(["red", "yellow", "green"], "blue");
์ด ํธ์ถ์์ ํ์ ์ธํฐํ์ด์ค๋ "ํ๋์(blue)"์ด "๋นจ๊ฐ์(red)" ๋๋ "๋ ธ๋์(yellow)" ๋๋ "๋ น์(green)"๊ณผ ๊ฐ์ด ํ์ ์ ํ๋น์ฑ์ด ์๋ค๊ณ ๊ฒฐ์ ํ๋ค. ๋ฐ๋ผ์ TypeScript๋ ํธ์ถ์ ๊ฑฐ๋ถํ๋ ๋์ , C[] ํ์ ์ "๋นจ๊ฐ์" | "๋ ธ๋์" | "๋ น์" | "ํ๋์"์ผ๋ก ์ถ๋ก ํ๋ค.
์ฌ๋๋ค์ด ํ์ฌ ์ด ๋ฌธ์ ๋ฅผ ์ฒ๋ฆฌํ๋ ํ ๊ฐ์ง ๋ฐฉ๋ฒ์ ๊ธฐ์กด ์ ํ ๋งค๊ฐ๋ณ์์ ์ํด ๊ฒฝ๊ณ์ง์ด์ง๋ ๋ณ๋์ ์ ํ ๋งค๊ฐ๋ณ์๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ด๋ค.
function createStreetLight<C extends string, D extends C>(colors: C[], defaultColor?: D) {
}
createStreetLight(["red", "yellow", "green"], "blue");
// ~~~~~~
// error!
// Argument of type '"blue"' is not assignable to parameter of type '"red" | "yellow" | "green" | undefined'.
์ด๊ฒ์ ํจ๊ณผ๊ฐ ์์ง๋ง, createStreetLight์ ๋ค๋ฅธ ๊ณณ์์๋ D๊ฐ ์ฌ์ฉ๋์ง ์์ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ์ฝ๊ฐ ์ด์ํ๋ค.
์ด๊ฒ์ด TypeScript 5.4๊ฐ ์๋ก์ด NoInfer ์ ํธ๋ฆฌํฐ ํ์
์ ๋์
ํ๋ ์ด์ ์ด๋ค. NoInfer<...>์ ํ์
์ ๋๋ฌ์ธ๋ฉด TypeScript์ ํ์
์ถ๋ก ์ ์ํ ํ๋ณด๋ฅผ ์ฐพ๊ธฐ ์ํด ๋ด๋ถ ํ์
๋ค์ ํ๊ณ ๋ค์ด ๋์กฐํ์ง ๋ง๋ผ๋ ์ ํธ๋ฅผ ์ค๋ค.
NoInfer๋ฅผ ์ฌ์ฉํ์ฌ CreateStreetLight๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ๋ค์ ์์ฑํ ์ ์๋ค:
function createStreetLight<C extends string>(colors: C[], defaultColor?: NoInfer<C>) {
// ...
}
createStreetLight(["red", "yellow", "green"], "blue");
// ~~~~~~
// error!
// Argument of type '"blue"' is not assignable to parameter of type '"red" | "yellow" | "green" | undefined'.
defaultColor์ ํ์
๋์์์ ์ ์ธํ๋ ๊ฒ์ "ํ๋์"์ด ๊ฒฐ์ฝ ์ธํฐํ์ด์ค ํ๋ณด๋ก ๋๋์ง ์๋๋ค๋ ๊ฒ์ ์๋ฏธํ๋ฉฐ, ์ ํ ๊ฒ์ฌ์๋ ์ด๋ฅผ ๊ฑฐ๋ถํ ์ ์๋ค.
๐ธ ์ถ์ฒ ๐ธ
'Etc' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[ Dev Tools ] ๊ฐ๋ฐ ํด ์ถ์ฒ. Lazy Git (1) | 2024.03.24 |
---|---|
[Docker] Docker ์ CI CD <01> (0) | 2024.03.11 |
[ Safari ] ์์ดํฐ์ ์ฌํ๋ฆฌ ๋ชจ๋ฐ์ผ ์น ๋๋ฒ๊น ํ๋ ๋ฐฉ๋ฒ (0) | 2023.05.14 |
[ ์ฑ ์ถ์ฒ ] ์ดํํฐ๋ธ ํ์ ์คํฌ๋ฆฝํธ (0) | 2023.03.12 |
[ ์ฑ ์ถ์ฒ ] Learning React (0) | 2023.01.30 |