๊ธฐ๋ณธ ํ์ดํ์ ๋์ด, ์กฐ๊ฑด๋ถ ํ์ , ํ ํ๋ฆฟ ๋ฆฌํฐ๋ด, ๋ฌธ์์ด ์กฐ์ ๊ฐ์ ๊ณ ๊ธ TypeScript ๊ธฐ๋ฅ์ผ๋ก ๊ฐ๋ ฅํ๊ณ ํ์ ์์ ํ API๋ฅผ ๊ตฌ์ถํ์ธ์. ๊ธ๋ก๋ฒ ๊ฐ๋ฐ์๋ฅผ ์ํ ์ข ํฉ ๊ฐ์ด๋.
TypeScript์ ์ ์ฌ๋ ฅ ์ต๋ํ ํ์ฉ: ์กฐ๊ฑด๋ถ ํ์ , ํ ํ๋ฆฟ ๋ฆฌํฐ๋ด, ๊ณ ๊ธ ๋ฌธ์์ด ์กฐ์ ์ฌ์ธต ๋ถ์
ํ๋ ์ํํธ์จ์ด ๊ฐ๋ฐ ์ธ๊ณ์์ TypeScript๋ JavaScript์ ๋จ์ํ ํ์ ๊ฒ์ฌ๊ธฐ๋ฅผ ๋์ด ํจ์ฌ ๋ ์งํํ์ต๋๋ค. ์ด์ ๋ ํ์ ๋ ๋ฒจ ํ๋ก๊ทธ๋๋ฐ์ด๋ผ๊ณ ์ค๋ช ํ ์ ์๋ ์ ๊ตํ ๋๊ตฌ๊ฐ ๋์์ต๋๋ค. ์ด ํจ๋ฌ๋ค์์ ํตํด ๊ฐ๋ฐ์๋ ํ์ ์์ฒด์ ๋ํด ์๋ํ๋ ์ฝ๋๋ฅผ ์์ฑํ์ฌ ๋์ ์ด๊ณ ์์ฒด ๋ฌธ์ํ๋๋ฉฐ ๋งค์ฐ ์์ ํ API๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค. ์ด ํ๋ช ์ ํต์ฌ์๋ ์กฐ๊ฑด๋ถ ํ์ , ํ ํ๋ฆฟ ๋ฆฌํฐ๋ด ํ์ , ๊ทธ๋ฆฌ๊ณ ๋ด์ฅ๋ ๋ฌธ์์ด ์กฐ์ ํ์ ์ ๋ชจ์์ด๋ผ๋ ์ธ ๊ฐ์ง ๊ฐ๋ ฅํ ๊ธฐ๋ฅ์ด ํจ๊ป ์์ฉํฉ๋๋ค.
์ ์ธ๊ณ ๊ฐ๋ฐ์๋ค์ด TypeScript ๊ธฐ์ ์ ํฅ์์ํค๊ธฐ ์ํด, ์ด๋ฌํ ๊ฐ๋ ์ ์ดํดํ๋ ๊ฒ์ ๋ ์ด์ ์ฌ์น๊ฐ ์๋๋ผ ํ์ฅ ๊ฐ๋ฅํ๊ณ ์ ์ง ๊ด๋ฆฌ ๊ฐ๋ฅํ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ๋ ๋ฐ ํ์์ ์ ๋๋ค. ์ด ๊ฐ์ด๋๋ ๊ธฐ๋ณธ ์์น์์ ์์ํ์ฌ ๋ณต์กํ๊ณ ์ค์ ์ ์ธ ํจํด์ผ๋ก ๋์๊ฐ ์ด๋ค์ ๊ฒฐํฉ๋ ํ์ ๋ณด์ฌ์ฃผ๋ ์ฌ์ธต์ ์ธ ๋ถ์์ ์ ๊ณตํฉ๋๋ค. ๋์์ธ ์์คํ , ํ์ ์์ API ํด๋ผ์ด์ธํธ ๋๋ ๋ณต์กํ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๊ตฌ์ถํ๋ ์ด๋ฌํ ๊ธฐ๋ฅ์ ๋ง์คํฐํ๋ฉด TypeScript ์ฝ๋ฉ ๋ฐฉ์์ด ๊ทผ๋ณธ์ ์ผ๋ก ๋ฐ๋ ๊ฒ์ ๋๋ค.
๊ธฐ๋ฐ: ์กฐ๊ฑด๋ถ ํ์ (`extends` ์ผํญ ์ฐ์ฐ์)
์กฐ๊ฑด๋ถ ํ์
์ ํ์
๊ด๊ณ ๊ฒ์ฌ์ ๋ฐ๋ผ ๋ ๊ฐ์ง ๊ฐ๋ฅํ ํ์
์ค ํ๋๋ฅผ ์ ํํ ์ ์๊ฒ ํฉ๋๋ค. JavaScript์ ์ผํญ ์ฐ์ฐ์(condition ? valueIfTrue : valueIfFalse)์ ์ต์ํ๋ค๋ฉด ๊ตฌ๋ฌธ์ด ๋ฐ๋ก ์ง๊ด์ ์ด๋ผ๋ ๊ฒ์ ์ ์ ์์ต๋๋ค.
type Result = SomeType extends OtherType ? TrueType : FalseType;
์ฌ๊ธฐ์ extends ํค์๋๋ ์กฐ๊ฑด ์ญํ ์ ํฉ๋๋ค. SomeType์ด OtherType์ ํ ๋น ๊ฐ๋ฅํ์ง ํ์ธํฉ๋๋ค. ๊ฐ๋จํ ์๋ก ๋ถํดํด ๋ณด๊ฒ ์ต๋๋ค.
๊ธฐ๋ณธ ์์ : ํ์ ํ์ธ
์ฃผ์ด์ง ํ์
T๊ฐ ๋ฌธ์์ด์ด๋ฉด true๋ฅผ, ๊ทธ๋ ์ง ์์ผ๋ฉด false๋ฅผ ๋ฐํํ๋ ํ์
์ ๋ง๋ค๊ณ ์ถ๋ค๊ณ ๊ฐ์ ํด ๋ณด๊ฒ ์ต๋๋ค.
type IsString
๊ทธ๋ฐ ๋ค์ ๋ค์๊ณผ ๊ฐ์ด ์ด ํ์ ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
type A = IsString<"hello">; // type A is true
type B = IsString<123>; // type B is false
์ด๊ฒ์ด ๊ธฐ๋ณธ์ ์ธ ๊ตฌ์ฑ ์์์
๋๋ค. ํ์ง๋ง ์กฐ๊ฑด๋ถ ํ์
์ ์ง์ ํ ํ์ infer ํค์๋์ ๊ฒฐํฉ๋ ๋ ๋ฐํ๋ฉ๋๋ค.
`infer`์ ํ: ๋ด๋ถ์์ ํ์ ์ถ์ถ
infer ํค์๋๋ ๊ฒ์ ์ฒด์ธ์ ์
๋๋ค. extends ์ ๋ด์์ ์๋ก์ด ์ ๋ค๋ฆญ ํ์
๋ณ์๋ฅผ ์ ์ธํ์ฌ ํ์ธ ์ค์ธ ํ์
์ ์ผ๋ถ๋ฅผ ํจ๊ณผ์ ์ผ๋ก ์บก์ฒํ ์ ์์ต๋๋ค. ํจํด ๋งค์นญ์์ ๊ฐ์ ๊ฐ์ ธ์ค๋ ํ์
๋ ๋ฒจ ๋ณ์ ์ ์ธ์ด๋ผ๊ณ ์๊ฐํ์ญ์์ค.
๊ณ ์ ์ ์ธ ์๋ Promise ๋ด์ ํฌํจ๋ ํ์
์ ๋ํ ํด์ ํ๋ ๊ฒ์
๋๋ค.
type UnwrapPromise
์ด๊ฒ์ ๋ถ์ํด ๋ด ์๋ค:
T extends Promise: ์ด๊ฒ์T๊ฐPromise์ธ์ง ํ์ธํฉ๋๋ค. ๊ทธ๋ ๋ค๋ฉด TypeScript๋ ๊ตฌ์กฐ๋ฅผ ์ผ์น์ํค๋ ค๊ณ ์๋ํฉ๋๋ค.infer U: ์ผ์น๊ฐ ์ฑ๊ณตํ๋ฉด TypeScript๋Promise๊ฐ resolve๋๋ ํ์ ์ ์บก์ฒํ์ฌU๋ผ๋ ์ ํ์ ๋ณ์์ ๋ฃ์ต๋๋ค.? U : T: ์กฐ๊ฑด์ด true(T๊ฐPromise์ธ ๊ฒฝ์ฐ)์ด๋ฉด ๊ฒฐ๊ณผ ํ์ ์U(๋ํ ํด์ ๋ ํ์ )์ ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ๊ฒฐ๊ณผ ํ์ ์ ์๋ ํ์T์ผ ๋ฟ์ ๋๋ค.
์ฌ์ฉ๋ฒ:
type User = { id: number; name: string; };
type UserPromise = Promise
type UnwrappedUser = UnwrapPromise
type UnwrappedNumber = UnwrapPromise
์ด ํจํด์ ๋งค์ฐ ์ผ๋ฐ์ ์ด๋ฏ๋ก TypeScript์๋ ํจ์์ ๋ฐํ ํ์
์ ์ถ์ถํ๊ธฐ ์ํด ๋์ผํ ์๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ๊ตฌํ๋๋ ReturnType์ ๊ฐ์ ๊ธฐ๋ณธ ์ ๊ณต ์ ํธ๋ฆฌํฐ ํ์
์ด ํฌํจ๋์ด ์์ต๋๋ค.
๋ถ์ฐ ์กฐ๊ฑด๋ถ ํ์ : ์ ๋์จ์ผ๋ก ์์
์กฐ๊ฑด๋ถ ํ์ ์ ํฅ๋ฏธ๋กญ๊ณ ์ค์ํ ๋์์ ํ์ธ ์ค์ธ ํ์ ์ด "๋ค์ดํค๋" ์ ๋ค๋ฆญ ํ์ ๋งค๊ฐ๋ณ์์ธ ๊ฒฝ์ฐ ๋ถ์ฐ์ ์ผ๋ก ๋ณํ๋ค๋ ๊ฒ์ ๋๋ค. ์ฆ, ์ ๋์จ ํ์ ์ ์ ๋ฌํ๋ฉด ์กฐ๊ฑด์ ์ ๋์จ์ ๊ฐ ๋ฉค๋ฒ์ ๊ฐ๋ณ์ ์ผ๋ก ์ ์ฉ๋๊ณ ๊ฒฐ๊ณผ๋ ๋ค์ ์๋ก์ด ์ ๋์จ์ผ๋ก ์์ง๋ฉ๋๋ค.
ํ์ ์ ํด๋น ํ์ ์ ๋ฐฐ์ด๋ก ๋ณํํ๋ ํ์ ์ ์๊ฐํด ๋ณด๊ฒ ์ต๋๋ค.
type ToArray
์ ๋์จ ํ์
์ ToArray์ ์ ๋ฌํ๋ฉด:
type StrOrNumArray = ToArray
๊ฒฐ๊ณผ๋ (string | number)[]๊ฐ ์๋๋๋ค. T๊ฐ ๋ค์ดํค๋ ํ์
๋งค๊ฐ๋ณ์์ด๊ธฐ ๋๋ฌธ์ ์กฐ๊ฑด์ด ๋ถ์ฐ๋ฉ๋๋ค.
ToArray์string[]๊ฐ ๋ฉ๋๋ค.ToArray๋number[]๊ฐ ๋ฉ๋๋ค.
์ต์ข
๊ฒฐ๊ณผ๋ ์ด๋ฌํ ๊ฐ๋ณ ๊ฒฐ๊ณผ์ ์ ๋์จ์
๋๋ค: string[] | number[].
์ด ๋ถ์ฐ ์์ฑ์ ์ ๋์จ์ ํํฐ๋งํ๋ ๋ฐ ๋งค์ฐ ์ ์ฉํฉ๋๋ค. ์๋ฅผ ๋ค์ด ๊ธฐ๋ณธ ์ ๊ณต Extract ์ ํธ๋ฆฌํฐ ํ์
์ ์ด๋ฅผ ์ฌ์ฉํ์ฌ ์ ๋์จ T์์ U์ ํ ๋น ๊ฐ๋ฅํ ๋ฉค๋ฒ๋ฅผ ์ ํํฉ๋๋ค.
์ด๋ฌํ ๋ถ์ฐ ๋์์ ๋ฐฉ์งํ๋ ค๋ฉด extends ์ ์ ์์ชฝ์์ ํ์
๋งค๊ฐ๋ณ์๋ฅผ ํํ๋ก ๋ํํ ์ ์์ต๋๋ค.
type ToArrayNonDistributive
type StrOrNumArrayUnified = ToArrayNonDistributive
์ด ๊ฒฌ๊ณ ํ ๊ธฐ๋ฐ์ ๋ฐํ์ผ๋ก ๋์ ๋ฌธ์์ด ํ์ ์ ๊ตฌ์ฑํ๋ ๋ฐฉ๋ฒ์ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
ํ์ ๋ ๋ฒจ์์ ๋์ ๋ฌธ์์ด ๊ตฌ์ถ: ํ ํ๋ฆฟ ๋ฆฌํฐ๋ด ํ์
TypeScript 4.1์์ ๋์ ๋ ํ ํ๋ฆฟ ๋ฆฌํฐ๋ด ํ์ ์ JavaScript์ ํ ํ๋ฆฟ ๋ฆฌํฐ๋ด ๋ฌธ์์ด๊ณผ ๊ฐ์ ๋ชจ์์ ํ์ ์ ์ ์ํ ์ ์๊ฒ ํด์ค๋๋ค. ์ด๋ฅผ ํตํด ๊ธฐ์กด ๋ฌธ์์ด ๋ฆฌํฐ๋ด ํ์ ์์ ์๋ก์ด ๋ฌธ์์ด ๋ฆฌํฐ๋ด ํ์ ์ ์ฐ๊ฒฐ, ๊ฒฐํฉ ๋ฐ ์์ฑํ ์ ์์ต๋๋ค.
๊ตฌ๋ฌธ์ ์์ํ๋ ๊ฒ๊ณผ ์ ํํ ๊ฐ์ต๋๋ค:
type World = "World";
type Greeting = `Hello, ${World}!`; // type Greeting์ "Hello, World!"
์ด๊ฒ์ ๊ฐ๋จํด ๋ณด์ผ ์ ์์ง๋ง, ์ ๋์จ ๋ฐ ์ ๋ค๋ฆญ๊ณผ ๊ฒฐํฉํ ๋ ๊ทธ ํ์ด ๋ฐํ๋ฉ๋๋ค.
์ ๋์จ๊ณผ ์์ด
ํ ํ๋ฆฟ ๋ฆฌํฐ๋ด ํ์ ์ ์ ๋์จ์ด ํฌํจ๋๋ฉด ๊ฐ๋ฅํ ๋ชจ๋ ๋ฌธ์์ด ์์ด์ ํฌํจํ๋ ์๋ก์ด ์ ๋์จ์ผ๋ก ํ์ฅ๋ฉ๋๋ค. ์ด๊ฒ์ ์ ์ ์๋ ์์ ์งํฉ์ ์์ฑํ๋ ๊ฐ๋ ฅํ ๋ฐฉ๋ฒ์ ๋๋ค.
CSS ๋ง์ง ์์ฑ ์งํฉ์ ์ ์ํ๋ค๊ณ ์์ํด ๋ณด๊ฒ ์ต๋๋ค.
type Side = "top" | "right" | "bottom" | "left";
type MarginProperty = `margin-${Side}`;
MarginProperty์ ๊ฒฐ๊ณผ ํ์
์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
"margin-top" | "margin-right" | "margin-bottom" | "margin-left"
์ด๊ฒ์ ํน์ ๋ฌธ์์ด ํ์๋ง ํ์ฉ๋๋ ํ์ ์์ ๊ตฌ์ฑ ์์ props ๋๋ ํจ์ ์ธ์๋ฅผ ๋ง๋๋ ๋ฐ ์ ํฉํฉ๋๋ค.
์ ๋ค๋ฆญ๊ณผ ๊ฒฐํฉ
ํ ํ๋ฆฟ ๋ฆฌํฐ๋ด์ ์ ๋ค๋ฆญ๊ณผ ํจ๊ป ์ฌ์ฉ๋ ๋ ์ง์ ์ผ๋ก ๋น์ ๋ฐํฉ๋๋ค. ์ ๋ ฅ์ ๊ธฐ๋ฐ์ผ๋ก ์๋ก์ด ๋ฌธ์์ด ๋ฆฌํฐ๋ด ํ์ ์ ์์ฑํ๋ ํฉํ ๋ฆฌ ํ์ ์ ๋ง๋ค ์ ์์ต๋๋ค.
type MakeEventListener
type UserListener = MakeEventListener<"user">; // "onUserChange"
type ProductListener = MakeEventListener<"product">; // "onProductChange"
์ด ํจํด์ ๋์ ์ด๊ณ ํ์
์์ ํ API๋ฅผ ๋ง๋๋ ํต์ฌ์
๋๋ค. ๊ทธ๋ฌ๋ ๋ฌธ์์ด์ ๋์๋ฌธ์๋ฅผ ์์ ํด์ผ ํ๋ ๊ฒฝ์ฐ(์: "user"๋ฅผ "User"๋ก ๋ณ๊ฒฝํ์ฌ "onUserChange"๋ฅผ ์ป๋ ๊ฒฝ์ฐ) ์ด๋ป๊ฒ ํด์ผ ํ ๊น์? ๋ฌธ์์ด ์กฐ์ ํ์
์ด ๋ฐ๋ก ๊ทธ๋ด ๋ ์ฌ์ฉ๋ฉ๋๋ค.
ํดํท: ๋ด์ฅ ๋ฌธ์์ด ์กฐ์ ํ์
ํ ํ๋ฆฟ ๋ฆฌํฐ๋ด์ ๋์ฑ ๊ฐ๋ ฅํ๊ฒ ๋ง๋ค๊ธฐ ์ํด TypeScript๋ ๋ฌธ์์ด ๋ฆฌํฐ๋ด์ ์กฐ์ํ๊ธฐ ์ํ ๊ธฐ๋ณธ ์ ๊ณต ํ์ ์งํฉ์ ์ ๊ณตํฉ๋๋ค. ์ด๊ฒ์ ์ ํธ๋ฆฌํฐ ํจ์์ ๊ฐ์ง๋ง ํ์ ์์คํ ์ ์ฌ์ฉ๋ฉ๋๋ค.
๋์๋ฌธ์ ์์ ์: `Uppercase`, `Lowercase`, `Capitalize`, `Uncapitalize`
์ด ๋ค ๊ฐ์ง ํ์ ์ ์ด๋ฆ์ด ๋ํ๋ด๋ ๋๋ก ์ ํํ ์ํํฉ๋๋ค.
Uppercase: ์ ์ฒด ๋ฌธ์์ด ํ์ ์ ๋๋ฌธ์๋ก ๋ณํํฉ๋๋ค.type LOUD = Uppercase<"hello">; // "HELLO"Lowercase: ์ ์ฒด ๋ฌธ์์ด ํ์ ์ ์๋ฌธ์๋ก ๋ณํํฉ๋๋ค.type quiet = Lowercase<"WORLD">; // "world"Capitalize: ๋ฌธ์์ด ํ์ ์ ์ฒซ ๊ธ์๋ฅผ ๋๋ฌธ์๋ก ๋ณํํฉ๋๋ค.type Proper = Capitalize<"john">; // "John"Uncapitalize: ๋ฌธ์์ด ํ์ ์ ์ฒซ ๊ธ์๋ฅผ ์๋ฌธ์๋ก ๋ณํํฉ๋๋ค.type variable = Uncapitalize<"PersonName">; // "personName"
์ด์ ์์ ๋ฅผ ๋ค์ ์ดํด๋ณด๊ณ Capitalize๋ฅผ ์ฌ์ฉํ์ฌ ๊ธฐ์กด ์ด๋ฒคํธ ํธ๋ค๋ฌ ์ด๋ฆ์ ์์ฑํ์ฌ ๊ฐ์ ํด ๋ณด๊ฒ ์ต๋๋ค.
type MakeEventListener
type UserListener = MakeEventListener<"user">; // "onUserChange"
type ProductListener = MakeEventListener<"product">; // "onProductChange"
์ด์ ๋ชจ๋ ์กฐ๊ฐ์ด ์ค๋น๋์์ต๋๋ค. ์ด ์กฐ๊ฐ๋ค์ด ๊ฒฐํฉ๋์ด ๋ณต์กํ๊ณ ์ค์ ์ ์ธ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ์ ์ดํด๋ด ์๋ค.
ํฉ์ฑ: ๊ณ ๊ธ ํจํด์ ์ํด ์ธ ๊ฐ์ง ๋ชจ๋ ๊ฒฐํฉ
์ด๊ฒ์ ์ด๋ก ์ด ์ค์ ์ ๋ง๋๋ ๊ณณ์ ๋๋ค. ์กฐ๊ฑด๋ถ ํ์ , ํ ํ๋ฆฟ ๋ฆฌํฐ๋ด ๋ฐ ๋ฌธ์์ด ์กฐ์์ ํจ๊ป ์ฎ์ด ๋งค์ฐ ์ ๊ตํ๊ณ ์์ ํ ํ์ ์ ์๋ฅผ ๊ตฌ์ถํ ์ ์์ต๋๋ค.
ํจํด 1: ์์ ํ์ ์์ ์ด๋ฒคํธ ์ด๋ฏธํฐ
๋ชฉํ: on(), off() ๋ฐ emit()๊ณผ ๊ฐ์ ๋ฉ์๋๊ฐ ์์ ํ ํ์
์์ ํ ์ ๋ค๋ฆญ EventEmitter ํด๋์ค๋ฅผ ๋ง๋ญ๋๋ค. ์ฆ:
- ๋ฉ์๋์ ์ ๋ฌ๋๋ ์ด๋ฒคํธ ์ด๋ฆ์ ์ ํจํ ์ด๋ฒคํธ์ฌ์ผ ํฉ๋๋ค.
emit()์ ์ ๋ฌ๋๋ ํ์ด๋ก๋๋ ํด๋น ์ด๋ฒคํธ์ ๋ํด ์ ์๋ ํ์ ๊ณผ ์ผ์นํด์ผ ํฉ๋๋ค.on()์ ์ ๋ฌ๋๋ ์ฝ๋ฐฑ ํจ์๋ ํด๋น ์ด๋ฒคํธ์ ๋ํ ์ฌ๋ฐ๋ฅธ ํ์ด๋ก๋ ํ์ ์ ํ์ฉํด์ผ ํฉ๋๋ค.
๋จผ์ ์ด๋ฒคํธ ์ด๋ฆ์์ ํ์ด๋ก๋ ํ์ ์ผ๋ก์ ๋งต์ ์ ์ํฉ๋๋ค.
interface EventMap {
"user:created": { userId: number; name: string; };
"user:deleted": { userId: number; };
"product:added": { productId: string; price: number; };
}
์ด์ ์ ๋ค๋ฆญ EventEmitter ํด๋์ค๋ฅผ ๋น๋ํ ์ ์์ต๋๋ค. EventMap ๊ตฌ์กฐ๋ฅผ ํ์ฅํด์ผ ํ๋ ์ ๋ค๋ฆญ ๋งค๊ฐ๋ณ์ Events๋ฅผ ์ฌ์ฉํฉ๋๋ค.
class TypedEventEmitter
private listeners: { [K in keyof Events]?: ((payload: Events[K]) => void)[] } = {};
// `on` ๋ฉ์๋๋ Events ๋งต์ ํค์ธ ์ ๋ค๋ฆญ `K`๋ฅผ ์ฌ์ฉํฉ๋๋ค.
on
if (!this.listeners[event]) {
this.listeners[event] = [];
}
this.listeners[event]?.push(callback);
}
// `emit` ๋ฉ์๋๋ ํ์ด๋ก๋๊ฐ ์ด๋ฒคํธ์ ํ์
๊ณผ ์ผ์นํ๋์ง ํ์ธํฉ๋๋ค.
emit
this.listeners[event]?.forEach(callback => callback(payload));
}
}
์ธ์คํด์คํํ์ฌ ์ฌ์ฉํด ๋ณด๊ฒ ์ต๋๋ค.
const appEvents = new TypedEventEmitter
// ์ด๊ฒ์ ํ์
์์ ํฉ๋๋ค. ํ์ด๋ก๋๋ { userId: number; name: string; }์ผ๋ก ์ฌ๋ฐ๋ฅด๊ฒ ์ถ๋ก ๋ฉ๋๋ค.
appEvents.on("user:created", (payload) => {
console.log(`์ฌ์ฉ์ ์์ฑ๋จ: ${payload.name} (ID: ${payload.userId})`);
});
// "user:updated"๊ฐ EventMap์ ํค๊ฐ ์๋๊ธฐ ๋๋ฌธ์ TypeScript์์ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
// appEvents.on("user:updated", () => {}); // ์ค๋ฅ!
// ํ์ด๋ก๋์ 'name' ์์ฑ์ด ์๊ธฐ ๋๋ฌธ์ TypeScript์์ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
// appEvents.emit("user:created", { userId: 123 }); // ์ค๋ฅ!
์ด ํจํด์ ์ ํต์ ์ผ๋ก ๋ง์ ์ ํ๋ฆฌ์ผ์ด์ ์์ ๋งค์ฐ ๋์ ์ด๊ณ ์ค๋ฅ๊ฐ ๋ฐ์ํ๊ธฐ ์ฌ์ด ๋ถ๋ถ์ ๋ํด ์ปดํ์ผ ์๊ฐ ์์ ์ฑ์ ์ ๊ณตํฉ๋๋ค.
ํจํด 2: ์ค์ฒฉ๋ ๊ฐ์ฒด์ ๋ํ ํ์ ์์ ๊ฒฝ๋ก ์ก์ธ์ค
๋ชฉํ: ์ ํ๊ธฐ๋ฒ ๋ฌธ์์ด ๊ฒฝ๋ก P(์: "user.address.city")๋ฅผ ์ฌ์ฉํ์ฌ ์ค์ฒฉ๋ ๊ฐ์ฒด T์์ ๊ฐ์ ํ์
์ ๊ฒฐ์ ํ ์ ์๋ ์ ํธ๋ฆฌํฐ ํ์
PathValue๋ฅผ ๋ง๋ญ๋๋ค.
์ด๊ฒ์ ์ฌ๊ท ์กฐ๊ฑด๋ถ ํ์ ์ ๋ณด์ฌ์ฃผ๋ ๊ณ ๋๋ก ๊ณ ๊ธ ํจํด์ ๋๋ค.
๋ค์์ ๋ถ์ํ ๊ตฌํ์ ๋๋ค.
type PathValue
? Key extends keyof T
? PathValue
: never
: P extends keyof T
? T[P]
: never;
์์ PathValue๋ก ๋
ผ๋ฆฌ๋ฅผ ์ถ์ ํด ๋ณด๊ฒ ์ต๋๋ค.
- ์ด๊ธฐ ํธ์ถ:
P๋"a.b.c"์ ๋๋ค. ์ด๊ฒ์ ํ ํ๋ฆฟ ๋ฆฌํฐ๋ด`${infer Key}.${infer Rest}`์ ์ผ์นํฉ๋๋ค. Key๋"a"๋ก ์ถ๋ก ๋ฉ๋๋ค.Rest๋"b.c"๋ก ์ถ๋ก ๋ฉ๋๋ค.- ์ฒซ ๋ฒ์งธ ์ฌ๊ท: ํ์
์
"a"๊ฐMyObject์ ํค์ธ์ง ํ์ธํฉ๋๋ค. ๊ทธ๋ ๋ค๋ฉดPathValue๋ฅผ ์ฌ๊ท์ ์ผ๋ก ํธ์ถํฉ๋๋ค. - ๋ ๋ฒ์งธ ์ฌ๊ท: ์ด์
P๋"b.c"์ ๋๋ค. ํ ํ๋ฆฟ ๋ฆฌํฐ๋ด๊ณผ ๋ค์ ์ผ์นํฉ๋๋ค. Key๋"b"๋ก ์ถ๋ก ๋ฉ๋๋ค.Rest๋"c"๋ก ์ถ๋ก ๋ฉ๋๋ค.- ํ์
์
"b"๊ฐMyObject["a"]์ ํค์ธ์ง ํ์ธํ๊ณPathValue๋ฅผ ์ฌ๊ท์ ์ผ๋ก ํธ์ถํฉ๋๋ค. - ๊ธฐ๋ณธ ์ผ์ด์ค: ๋ง์ง๋ง์ผ๋ก
P๋"c"์ ๋๋ค. ์ด๊ฒ์`${infer Key}.${infer Rest}`์ ์ผ์นํ์ง ์์ต๋๋ค. ํ์ ๋ ผ๋ฆฌ๋ ๋ ๋ฒ์งธ ์กฐ๊ฑด์ผ๋ก ๋์ด๊ฐ๋๋ค:P extends keyof T ? T[P] : never. - ํ์
์
"c"๊ฐMyObject["a"]["b"]์ ํค์ธ์ง ํ์ธํฉ๋๋ค. ๊ทธ๋ ๋ค๋ฉด ๊ฒฐ๊ณผ๋MyObject["a"]["b"]["c"]์ ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉดnever์ ๋๋ค.
ํฌํผ ํจ์์ ํจ๊ป ์ฌ์ฉ:
declare function get
const myObject = {
user: {
name: "Alice",
address: {
city: "Wonderland",
zip: 12345
}
}
};
const city = get(myObject, "user.address.city"); // const city: string
const zip = get(myObject, "user.address.zip"); // const zip: number
const invalid = get(myObject, "user.email"); // const invalid: never
์ด ๊ฐ๋ ฅํ ํ์ ์ ๊ฒฝ๋ก์ ์คํ๋ก ์ธํ ๋ฐํ์ ์ค๋ฅ๋ฅผ ๋ฐฉ์งํ๊ณ ๋ณต์กํ API ์๋ต์ ์ฒ๋ฆฌํ๋ ๊ธ๋ก๋ฒ ์ ํ๋ฆฌ์ผ์ด์ ์์ ํํ ๋ฐ์ํ๋ ๋ฌธ์ ์ธ ๊น์ด ์ค์ฒฉ๋ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ ๋ํ ์๋ฒฝํ ํ์ ์ถ๋ก ์ ์ ๊ณตํฉ๋๋ค.
๋ชจ๋ฒ ์ฌ๋ก ๋ฐ ์ฑ๋ฅ ๊ณ ๋ ค ์ฌํญ
๋ค๋ฅธ ๊ฐ๋ ฅํ ๋๊ตฌ์ ๋ง์ฐฌ๊ฐ์ง๋ก ์ด๋ฌํ ๊ธฐ๋ฅ์ ํ๋ช ํ๊ฒ ์ฌ์ฉํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.
- ๊ฐ๋ ์ฑ ์ฐ์ ์์ ์ง์ : ๋ณต์กํ ํ์ ์ ๋น ๋ฅด๊ฒ ์ฝ์ ์ ์๊ฒ ๋ ์ ์์ต๋๋ค. ๋ ์๊ณ ์ด๋ฆ์ด ์ ์ง์ ๋ ํฌํผ ํ์ ์ผ๋ก ๋ถํดํฉ๋๋ค. ๋ณต์กํ ๋ฐํ์ ์ฝ๋์ ๋ง์ฐฌ๊ฐ์ง๋ก ์ฃผ์์ ์ฌ์ฉํ์ฌ ๋ ผ๋ฆฌ๋ฅผ ์ค๋ช ํฉ๋๋ค.
- `never` ํ์
์ดํด:
neverํ์ ์ ์กฐ๊ฑด๋ถ ํ์ ์์ ์ค๋ฅ ์ํ๋ฅผ ์ฒ๋ฆฌํ๊ณ ์ ๋์จ์ ํํฐ๋งํ๊ธฐ ์ํ ๊ธฐ๋ณธ ๋๊ตฌ์ ๋๋ค. ๋ฐ์ํด์๋ ์ ๋๋ ์ํ๋ฅผ ๋ํ๋ ๋๋ค. - ์ฌ๊ท ์ ํ์ ์ฃผ์: TypeScript์๋ ํ์ ์ธ์คํด์คํ์ ๋ํ ์ฌ๊ท ๊น์ด ์ ํ์ด ์์ต๋๋ค. ํ์ ์ด ๋๋ฌด ๊น์ด ์ค์ฒฉ๋๊ฑฐ๋ ๋ฌดํ ์ฌ๊ท์ ์ธ ๊ฒฝ์ฐ ์ปดํ์ผ๋ฌ์์ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค. ์ฌ๊ท ํ์ ์ ๋ช ํํ ๊ธฐ๋ณธ ์ผ์ด์ค๊ฐ ์๋์ง ํ์ธํฉ๋๋ค.
- IDE ์ฑ๋ฅ ๋ชจ๋ํฐ๋ง: ๋งค์ฐ ๋ณต์กํ ํ์ ์ ๋๋๋ก TypeScript ์ธ์ด ์๋ฒ์ ์ฑ๋ฅ์ ์ํฅ์ ๋ฏธ์ณ ํธ์ง๊ธฐ์์ ์๋ ์์ฑ ๋ฐ ํ์ ๊ฒ์ฌ๊ฐ ๋๋ ค์ง ์ ์์ต๋๋ค. ์๋ ์ ํ๊ฐ ๋ฐ์ํ๋ ๊ฒฝ์ฐ ๋ณต์กํ ํ์ ์ ๋จ์ํํ๊ฑฐ๋ ๋ถํดํ ์ ์๋์ง ํ์ธํฉ๋๋ค.
- ์ค์ง ์๊ธฐ ์๊ธฐ: ์ด๋ฌํ ๊ธฐ๋ฅ์ ํ์ ์์ ์ฑ ๋ฐ ๊ฐ๋ฐ์ ๊ฒฝํ์ ๋ณต์กํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํ ๊ฒ์ ๋๋ค. ๊ฐ๋จํ ํ์ ์ ๊ณผ๋ํ๊ฒ ์์ง๋์ด๋งํ๋ ๋ฐ ์ฌ์ฉํ์ง ๋ง์ญ์์ค. ๋ชฉํ๋ ๋ถํ์ํ ๋ณต์ก์ฑ์ ์ถ๊ฐํ๋ ๊ฒ์ด ์๋๋ผ ๋ช ํ์ฑ๊ณผ ์์ ์ฑ์ ํฅ์์ํค๋ ๊ฒ์ ๋๋ค.
๊ฒฐ๋ก
์กฐ๊ฑด๋ถ ํ์ , ํ ํ๋ฆฟ ๋ฆฌํฐ๋ด ๋ฐ ๋ฌธ์์ด ์กฐ์ ํ์ ์ ๊ฒฉ๋ฆฌ๋ ๊ธฐ๋ฅ์ด ์๋๋ผ ํ์ ๋ ๋ฒจ์์ ์ ๊ตํ ๋ ผ๋ฆฌ๋ฅผ ์ํํ๊ธฐ ์ํ ๊ธด๋ฐํ๊ฒ ํตํฉ๋ ์์คํ ์ ๋๋ค. ์ด๋ฅผ ํตํด ๋จ์ํ ์ฃผ์์ ๋์ด ์์ฒด ๊ตฌ์กฐ์ ์ ์ฝ ์กฐ๊ฑด์ ๊น์ด ์ธ์ํ๋ ์์คํ ์ ๊ตฌ์ถํ ์ ์์ต๋๋ค.
์ด ์ธ ๊ฐ์ง๋ฅผ ๋ง์คํฐํ๋ฉด ๋ค์์ ์ํํ ์ ์์ต๋๋ค.
- ์์ฒด ๋ฌธ์ํ API ๋ง๋ค๊ธฐ: ํ์ ์์ฒด๊ฐ ๋ฌธ์๊ฐ ๋์ด ๊ฐ๋ฐ์๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ์ฌ์ฉํ๋๋ก ์๋ดํฉ๋๋ค.
- ์ ์ฒด ๋ฒ๊ทธ ํด๋์ค ์ ๊ฑฐ: ํ์ ์ค๋ฅ๋ ํ๋ก๋์ ํ๊ฒฝ์์ ์ฌ์ฉ์๊ฐ ์๋ ์ปดํ์ผ ์๊ฐ์ ํฌ์ฐฉ๋ฉ๋๋ค.
- ๊ฐ๋ฐ์ ๊ฒฝํ ๊ฐ์ : ์ฝ๋๋ฒ ์ด์ค์ ๊ฐ์ฅ ๋์ ์ธ ๋ถ๋ถ์์๋ ํ๋ถํ ์๋ ์์ฑ ๋ฐ ์ธ๋ผ์ธ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ์ฆ๊ธฐ์ญ์์ค.
์ด๋ฌํ ๊ณ ๊ธ ๊ธฐ๋ฅ์ ์์ฉํ๋ฉด TypeScript๊ฐ ์์ ๋ง์์ ๊ฐ๋ฐ์ ๊ฐ๋ ฅํ ํํธ๋๋ก ๋ณ๋ชจํฉ๋๋ค. ๋ณต์กํ ๋น์ฆ๋์ค ๋ ผ๋ฆฌ ๋ฐ ๋ถ๋ณ์ฑ์ ํ์ ์์คํ ์ ์ง์ ์ธ์ฝ๋ฉํ์ฌ ์ ํ๋ฆฌ์ผ์ด์ ์ด ๊ธ๋ก๋ฒ ์ฒญ์ค์๊ฒ ๋์ฑ ๊ฐ๋ ฅํ๊ณ ์ ์ง ๊ด๋ฆฌ ๊ฐ๋ฅํ๋ฉฐ ํ์ฅ ๊ฐ๋ฅํ๋๋ก ๋ณด์ฅํ ์ ์์ต๋๋ค.