โ ๋๋ฝ๋ ์๊ตฌ์ฌํญ์ ๊ฐ์ฅ ์์ ํ๊ธฐ ํ๋ ์ค๋ฅ๋ค. โ
- Robert L. Glass
์ ๋ช ํ ๋ฏธ๊ตญ ์ํํธ์จ์ด ์์ง๋์ด ๋ฐ ์๊ฐ

๊ณ ๊ธ ํ์ - Conditional Types
์กฐ๊ฑด๋ถ ํ์ (conditional type)์ด๋ ์ ๋ ฅ๋ ์ ๋ค๋ฆญ ํ์ ์ ๋ฐ๋ผ ํ์ ์ ๊ฒฐ์ ๊ธฐ๋ฅ์ ๋งํ๋ค.

์์ ๊ฐ์ด ์กฐ๊ฑด๋ถ ํ์
๋ฌธ๋ฒ์ extends ํค์๋์ ๋ฌผ์ํ ? ๊ธฐํธ๋ฅผ ์ฌ์ฉํ๋๋ฐ, ๋ณด์๋ง์ ์ผํญ ์ฐ์ฐ์๊ฐ ์๊ฐ ๋ฌ์ ๊ฒ์ด๋ค.
์ฌ๋ฌ๋ถ์ด ์ ์ถํ ๋ฐ์ ๊ฐ์ด, ์๋ฐ์คํฌ๋ฆฝํธ์ ์ผํญ ์ฐ์ฐ์๋ ๋ณ์์ ๊ฐ์ ์กฐ๊ฑด์ ๋ฐ๋ผ ๊ฒฐ์ ํ๋ ๊ฒ์ด๋ผ๋ฉด, ํ์ ์คํฌ๋ฆฝํธ์ ์กฐ๊ฑด๋ถ ํ์ ์ ๊ฐ ๋์ ํ์ ์ ์กฐ๊ฑด์ ๋ฐ๋ผ ๊ฒฐ์ ํ๋ ๊ฒ์ด๋ผ๊ณ ๋ณด๋ฉด ๋๋ค.
์์ ์กฐ๊ฑด๋ถ ํ์ ์ฝ๋ ๋ฌธ๋ฒ์ ํ์ดํด๋ณด์๋ฉด, ํ์ ์ T๊ฐ U์ ํ ๋น๋ ์ ์์ผ๋ฉด ํ์ ์ X๊ฐ ๋๊ณ ๊ทธ๋ ์ง ์๋ค๋ฉด ํ์ ์ด Y๊ฐ ๋๋ค๋ ๊ฒ์ ์๋ฏธํ๋ค.
์ฐฉ๊ฐํ์ง ๋ง์์ผ ํ ์ ์ ์กฐ๊ฑด๋ถ ํ์ ๋ ์ ๋์จ ์ฒ๋ผ ํ๋์ ํ์ ์ด๋ผ๋ ๊ฒ์ด๋ค.
extends ํค์๋๊ฐ ๋ค์ด๊ฐ์ ์ ๋ค๋ฆญ ๊บพ์ ๊ดํธ <> ์์ ์จ์ผ ํ๋์ค ์๋๋ฐ, ๊ทธ๋ฅ ๋ณ๊ฐ์ ํ์
๋ฌธ๋ฒ์ผ๋ก ์ทจ๊ธ๋๋ค๊ณ ๋ณด๋ฉด ๋๋ค.
์ ๋ค๋ฆญ extends ์ ์กฐ๊ฑด๋ถ ํ์ extends๋ ์ญํ ๋ง ๊ฐ์ ์๋ก ๋ค๋ฅธ ์ฌ์ฉ์ฒ ์ฐ์ฐ์๋ผ๊ณ ์น๋ถํ๋๊ฒ ์ดํดํ๊ธฐ ์ข๋ค.
์ด๋ฅผ ์ค์ ์ฝ๋๋ก ์จ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ด ๋ ์ ์๋ค.
// T extends U ? X : Y
// ์ ๋ค๋ฆญ์ด string์ด๋ฉด ๋ฌธ์์ด๋ฐฐ์ด, ์๋๋ฉด ๋๋ฒ๋ฐฐ์ด
type IsStringType<T> = T extends string ? string[] : number[];
type T1 = IsStringType<string>; // type T1 = string[]
type T2 = IsStringType<number>; // type T2 = number[]
const a: T1 = ['ํ๊ธธ๋', '์๊บพ์ ', '๋ฐํ๊ฑฐ์ธ'];
const b: T2 = [1000, 2000, 3000];
// ์ ๋ค๋ฆญ `T`๋ `boolean` ํ์
์ผ๋ก ์ ํ.
// ์ ๋ค๋ฆญ T์ true๊ฐ ๋ค์ด์ค๋ฉด string ํ์
์ผ๋ก, false๊ฐ ๋ค์ด์ค๋ฉด number ํ์
์ผ๋ก data ์์ฑ์ ํ์
์ง์
interface isDataString<T extends boolean> {
data: T extends true ? string : number;
isString: T;
}
const str: isDataString<true> = {
data: 'ํ๊ธธ๋', // String
isString: true,
};
const num: isDataString<false> = {
data: 9999, // Number
isString: false,
};
๋จ, ์กฐ๊ฑด๋ถ ํ์ ์ ์ค์ฒฉํด์ ์ฐ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ๊ฐ๋ ์ฑ์ด ๋งค์ฐ ์์ข์์ง๋ ๊ฐ์ํด์ผ ๋๋ค.
์ฐ๋ฆฌ๊ฐ ๋ณ์๋ฅผ ์กฐ๊ฑด๋ฌธ์ ํตํด ์ ๊ธฐ์ ์ผ๋ก ๋ค๋ฃฐ์ ์๋ ๊ฒ์ฒ๋ผ, ํ์ ์คํฌ๋ฆฝํธ์์ ํ์ ๋ ์ ๊ธฐ์ ์ผ๋ก ๋ค๋ฃจ๊ธฐ ์ํด, if๋ฌธ์ ์ธ์๋ ์์ผ๋ ์ด๋ฐ์์ผ๋ก ์ผํญ ์ฐ์ฐ์๋ฅผ ์ค์ฒฉํด์ ์จ์ผํ๋ ํ๊ณ๊ฐ ์๋ค.
type TypeName<T> =
T extends string ? "string" :
T extends number ? "number" :
T extends boolean ? "boolean" :
T extends undefined ? "undefined" :
T extends Function ? "function" :
"object";
type T0 = TypeName<string>; // "string"
type T1 = TypeName<"a">; // "string"
type T2 = TypeName<true>; // "boolean"
type T3 = TypeName<() => void>; // "function"
type T4 = TypeName<string[]>; // "object"
๋ถ์ฐ ์กฐ๊ฑด๋ถ ํ์
์ฌ๊ธฐ๊น์ง ๋ณด๋ฉด ์ผํญ ์ฐ์ฐ์ ์๋ฆฌ ์ ๋๋ ํ๋ก๊ทธ๋๋ฐ ์์ด๋ณด ๋ฑ์ง ๋์ ๋ ์ด๋ฏธ ์ตํ๋ ๊ฒ์ด๋ผ, ๊ฐ๋จํ ๋์ด๊ฐ๋ฉด ๋๊ฒ ์ง ๋ผ๊ณ ์๊ฐํ๊ฒ ์ง๋ง, ์ง์ง ์ง์ฅ์ ์ด์ ๋ถํฐ ์ด๋ค.

๋ค์ ์กฐ๊ฑด๋ถ ํ์ ์ฝ๋๋ฅผ ๋ณด์.
์ด๋ฒ์๋ ์ ๋์จ ํ์ ์ ์ ๋ค๋ฆญ์ ํ ๋นํ๋ค. ๊ฒฐ๊ณผ๊ฐ ์ด๋ป๊ฒ ๋์ฌ๊น?
type IsStringType<T> = T extends string ? 'yes' : 'no';
type T1 = IsStringType<string | number>;
string | number ๋ string ๋๋ number ์ด๋ ๋น์ฐํ string์ ํฌํจ๋๋ ์ผํญ ์ฐ์ฐ์์ ๊ฒฐ๊ณผ๋ 'yes'๊ฐ ๋์ด type T1์ ํ์
์ 'yes'๊ฐ ๋จ์ ์ ์ถ ํ ์ ์๋ค.
๊ทธ๋ฌ๋ ๋๋๊ฒ๋ ํ์
์ 'yes' | 'no' ๋ก ์ถ๋ก ๋๋ค.

์ด๊ฒ์ด ๋ถ์ฐ ์กฐ๊ฑด๋ถ ํ์ (distributive conditional types)์ด๋ค.
๋ถ์ฐ ์กฐ๊ฑด๋ถ ํ์ ์ ํ์ ์ ์ธ์คํฐํ ์ค์ ์๋์ผ๋ก ์ ๋์ธ ํ์ ์ผ๋ก ๋ถ์ฐ๋๋๋ฐ,
์๋ฅผ๋ค์ด, T์ ๋ํ ํ์
์ธ์ A | B | C ๋ฅผ ์ฌ์ฉํ์ฌ T extends U ? X : Y ๋ฅผ ์ธ์คํด์คํํ๋ฉด (A extends U ? X : Y) | (B extends U ? X : Y) | (C extends U ? X : Y) ๋ก ๊ฒฐ์ ๋๊ฒ ๋๋ค.
ํ๋ง๋๋ก ์ ๋์จ์ผ๋ก ๋ฌถ์ธ ํ์ ํ๋ํ๋ ๋ง๋ค ์กฐ๊ฑด๋ถ ํ์ ๊ฒ์ฌ๋ฅผ ํ๊ณ ๊ทธ ๊ฒฐ๊ณผ๊ฐ๋ค์ ๋ฌถ์ด ๋ค์ ์ ๋์จ์ผ๋ก ๋ฐํํ๋ ๊ฒ์ด๋ค.
๋ฐ๋ผ์ ์์ ํ์ ๊ฒฐ๊ณผ๋ฅผ ํ์ดํด๋ณด์๋ฉด ๋ค์๊ณผ ๊ฐ์ด ๋๋ค.

(string | number) extends string ? 'yes' : 'no'(string extends string ? 'yes' : 'no')|(number extends string ? 'yes' : 'no')'yes' | 'no'
ํ๊ฐ์ง ๋ ๋ง์ ์ ๋ถ๋ ค๋ณด๊ฒ ๋ค.
๋ค์ ๋ ์์ ์ฝ๋์ ๊ฒฐ๊ณผ ํ์ ์ ์ถ๋ก ํด๋ณด์.
type T3 = string | number extends string ? 'yes' : 'no';
type T4 = Array<string | number>;

๊นจ์ง๋ฏํ ๋จธ๋ฆฌ๋ฅผ ๊ฒจ์ฐ ์์ ํ ํ์๋๋ฐ ๋ค์ ๋ฐ์ด ๋ ๊ฒ ๊ฐ๋ค.
์ด๋ฒ์ ๋์ฒด ๋ฌด์จ ์๋ฆฌ์ ์ํด ์ ๋ ๊ฒ ๋ฐ๋๋ก ๋๋ ๊ฒ์ผ๊น?
type T3 ๊ฐ์ ๊ฒฝ์ฐ๋ ๊ทธ๋ฅ ์ ๋ค๋ฆญ๋ง ์์ผ์ ๋ฟ์ด์ง ์ฒ์ ์์ ์ ๋๊ฐ์ ์ฝ๋์ด๋ค. ์ ๋ค๋ฆญ์ ๋นผ๊ณ T ์๋ฆฌ์ ์ ๋์จ ํ์
์ ์ง์ ๋ฃ์์ ๋ฟ์ธ๋ฐ ์ ๊ฒฐ๊ณผ๊ฐ ๋ดํ์ด ๋ ๊ฒ์ผ๊น?
์ด๊ฒ ์ญ์ ๋ถ์ฐ ์กฐ๊ฑด๋ถ ํ์ (distributive conditional types) ์ ํน์ง์ด๋ค.
์กฐ๊ฑด๋ถ ํ์ (conditional types) ์์ (naked) type parameter ๊ฐ ์ฌ์ฉ๋ ๊ฒฝ์ฐ์๋ง ๋ถ์ฐ(distributive) ๋ฐฉ์์ผ๋ก ๋์ํ๊ฒ ๋๋ค.
(naked) type parameter๋ ์ ๋ค๋ฆญ T ์ ๊ฐ์ด ์๋ฏธ๊ฐ ์๋ ํ์ ํ๋ผ๋ฏธํฐ๋ฅผ ๋งํ๋ ๊ฒ์ด๋ฉฐ,
๋ง์ผ ์ง์ ๋ฆฌํฐ๋ด ํ์ ์ ๋ช ์ํ๊ฑฐ๋ ํน์ ์ ๋ค๋ฆญ T[] ์ ๊ฐ์ด ๋ณํ๋ ํ์ ํ๋ผ๋ฏธํฐ์ด๋ฉด, naked ๊ฐ ์๋๊ฒ ๋๋ค.
๋ฐ๋ผ์ ์ฒ์์ ๋ถ์ฐ ์กฐ๊ฑด๋ถ ํ์ ์์ ๋ ์ ๋ค๋ฆญ T๋ฅผ ์จ์ ๊ทธ๋๋ก ๋ถ์ฐ์ด ๋์ด ์ ๋์จ ํ์ ์ผ๋ก ํ์ ๊ฒฐ๊ณผ๊ฐ ๋ฐํ ๋ฌ์ง๋ง, ์ ๋์จ ํ์ ์ ์ ๋ค๋ฆญ์ด ์๋๋ผ ์ง์ ๋ฆฌํฐ๋ด๋ก ๋ฃ๊ฒ๋๋ฉด, ๋ถ์ฐ์ด ์ผ์ด๋์ง ์์๊ธฐ ๋๋ฌธ์ ์์ ๊ฒฐ๊ณผ๊ฐ ๋์จ ๊ฒ์ด๋ค.
์ด ํน์ง์ ์ด์ ๋ฆฌ ํ์๋ฉด ๋ค์ ์ฝ๋ ์์ ๊ฐ ๋ ์๊ฐ ์๋ค.
type T1 = (1 | 3 | 5 | 7) extends number ? 'yes' : 'no'; // naked ํ์
์ด ์๋๋ผ์ ๋ถ์ฐ์ด ๋์ง ์๋๋ค.
type T2<T> = T extends number ? T[] : 'no'; // ์ ๋ค๋ฆญ T๋ naked ํ์
์ด๋ผ ๋ถ์ฐ์ด ๋๋ค.
type T3<T> = T[] extends number ? 'yes' : T[]; // ์ ๋ค๋ฆญ์ด์ง๋ง T[] ์ ๊ฐ์ด ๋ณํ๋ ํ์
ํ๋ผ๋ฏธํฐ๋ naked ํ์
์ด ์๋๋ผ์ ๋ถ์ฐ์ด ์ผ์ด๋์ง ์๋๋ค.
type T4 = T1; // "yes"
type T5 = T2<(1 | 3 | 5 | 7)>; // 1[] | 3[] | 5[] | 7[]
type T6 = T2<(1 | 3 | 5 | 7)>; // (1 | 3 | 5 | 7)[]
๊ทธ๋ฆฌ๊ณ ๋๋ฒ์งธ์ ๊ฒฝ์ฐ type T4 = Array<string | number> ์ด๋ ต๊ฒ ์๊ฐํ ํ์์์ด, ์ธํฐํ์ด์ค Array<T> ๋ ํ์
์คํฌ๋ฆฝํธ์์ ๊ธฐ๋ณธ์ผ๋ก ์ง์๋๋ ์ ๋ค๋ฆญ ์ธํฐํ์ด์ค๋ก์ ๋น์ฐํ ์ฌ๊ธฐ์๋ ์กฐ๊ฑด๋ถ ํ์
(์ผํญ ์ฐ์ฐ์)์ด ์ฌ์ฉ๋์ง ์์ ๋น์ฐํ ๋ฐํ ๊ฐ์ ์ ๋์จ ๋ฐฐ์ด (string | number)[] ์ด ๋๊ฒ ๋๋ค.

๋ถ์ฐ ์กฐ๊ฑด๋ถ ํ์ ์์์ never
๋ถ์ฐ ์กฐ๊ฑด๋ถ์ ๋ถ์ฐ ์๋ฆฌ์๋ ๋ ํ๊ฐ์ง์ ํน๋ณํ ์ฅ์น๊ฐ ์๋๋ฐ never ํ์ ์ผ๋ก ๋ถ์ฐ์ด ๋ฌ์ ๊ฒฝ์ฐ ์ด ํ์ ์ ์ ์ธ ์ํจ๋ค๋ ํน์ง์ด ์๋ค.
์๋ฅผ ๋ค์ด ๋ค์๊ณผ ๊ฐ์ด number | string | object ๋ฅผ ๋ถ์ฐ ์กฐ๊ฑด๋ถ ํ์
์ ๋ค๋ฆญ์ ์ค๋ค๊ณ ํ์๋, ๊ฒฐ๊ณผ๋ number | never | never ๊ฐ ๋๋ ์ค ์๊ฒ ์ง๋ง, ๋ถ์ฐ ์กฐ๊ฑด๋ถ ํ์
์์์ never๋ ์ ์ธ๋ฅผ ์๋ฏธํ๊ธฐ์ ๊ทธ๋ฅ ํ์
์ ์์ ๋ฒ๋ ค number ๋ง ๋ฐํ๋๊ฒ ๋๋ค.
type Never<T> = T extends number ? T : never;
type Types = number | string | object;
type T2 = Never<Types>; // type T2 = number
(number extends number ? T : never) | (string extends number ? T : never) | (object extends number ? T : never)number | never | nevernumber
์ด๋ฅผ ์ด์ฉํด ๋ค์๊ณผ ๊ฐ์ด,
๋ ํ์ ์ธ์๋ฅผ ๋ฐ์ ํด๋นํ๋ ํ์ ์ ์ ์ธ์ํค๋ Exclude ์กฐ๊ฑด๋ถ ํ์ ๊ณผ
๋ ํ์ ์ธ์๋ฅผ ๋ฐ์ ํด๋นํ๋ ํ์ ๋ง ๋ชจ์ ๋ฐํ ์ํค๋ Extract ์กฐ๊ฑด๋ถ ํ์ ์ ๋ค์๊ณผ ๊ฐ์ด ๊ตฌํ ํ ์ ์๋ค.
๋์ ์ฐจ์ด์ ์ never ์์น๊ฐ ์๋ค์ธ ์ ๋ฐ์ ์๋ค.
// ์ ๋์จ ํ์
์ ๋ฐ์ T์ U๋ฅผ ๋น๊ตํด U์ ๊ฒน์น๋ ํ์
๋ค์ ์ ์ธํ T๋ฅผ ๋ฐํํ๋ ํ์
type My_Exclude<T, U> = T extends U ? never : T;
type T2 = My_Exclude<(1 | 3 | 5 | 7), (1 | 5 | 9)>; // U ์ ๋ค๋ฆญ(1 | 5 | 9)์ ์ํด์์ง ์์ 3 | 7 ๋ง ๋ฐํ๋จ
type T3 = My_Exclude<string | number | (() => void), Function>; // U ์ ๋ค๋ฆญ(Function)์ ์ํด์์ง ์์ string | number ๋ง ๋ฐํ ๋จ
export {};
// ์ ๋์จ ํ์
์ ๋ฐ์ T์ U๋ฅผ ๋น๊ตํด U์ ๊ฒน์น๋ ํ์
๋ค๋ง ์ฌ๊ตฌ์ฑํด T๋ฅผ ๋ฐํํ๋ ํ์
type My_Extract<T, U> = T extends U ? T : never;
type T4 = My_Extract<(1 | 3 | 5 | 7), (1 | 5 | 9)>; // U ์ ๋ค๋ฆญ์(1 | 5 | 9) ์ํด์๋ 1 | 5 ๋ง ๋ฐํ๋จ
export {};
infer ํค์๋
T extends infer U ? X : Y
infer ํค์๋ ์๋ฆฌ๋ ํ์
์คํฌ๋ฆฝํธ๊ฐ ์์ง์ด ๋ฐํ์ ์ํฉ์์ ํ์
์ ์ถ๋ก ํ ์ ์๋๋ก ํ๊ณ , ์ถ๋ก ํ ํ์
๊ฐ์ infer ํ์
ํ๋ผ๋ฏธํฐ U ์ ํ ๋นํด์ค๋ค. ๊ทธ๋ฆฌ๊ณ ์กฐ๊ฑด๋ถ ํ์
์ ์ํด์ ํจ์์ ํํ๊ฐ ์ฐธ์ด๋ผ๋ฉด ํ๋ผ๋ฏธํฐ๋ฅผ ์๋๋ผ๋ฉด ๋ฌด์(never) ํ๋๊ฒ ๊ธฐ๋ณธ ๋์์ด๋ค.
์์ ๋ฌธ๋ฒ์์ ๋ณผ์ ์๋ฏ์ด, inferํค์๋๋ ์กฐ๊ฑด๋ถ ํ์ ์์ extends๋ค์ ์ฌ์ฉ๋๋ ๊ท์น์ ๊ฐ๊ณ ์๋ค.
์งง๊ฒ ์ดํด๋ณด๋ฉด, ์ ๋ค๋ฆญ T ์ { a: string, b: string } ๊ฐ์ฒด ํ์
์ด ๋ค์ด๊ฐ์ infer U ์ ์ํด string์ด ์ถ๋ก ๋์ด ์ฐธ์ด ๋์ด ์๊ธฐ ์์ ์ ํ์
U๊ฐ ๋ฐํ๋จ์ ์์ ์๋ค.
type Foo<T> = T extends { a: infer U, b: infer U } ? U : never;
type T10 = Foo<{ a: string, b: string }>; // string
type T11 = Foo<{ a: string, b: number }>; // string | number
infer๋ ํนํ ํจ์๋ฅผ ์ถ๋ก ํ๋๋ฐ ์์ด ์ ์ฉํ๊ฒ ์ฌ์ฉ๋๋๋ฐ, ๋ค์๊ณผ ๊ฐ์ด ํจ์์ ์ธ์ x ์ ํ์
์ ์ถ๋ก infer U ํ์ฌ ํ์
์ ๋ฐํํ๋๊ฑธ ์์ ์๋ค.
type Bar<T> = T extends { a: (x: infer U) => void, b: (x: infer U) => void } ? U : never;
type T20 = Bar<{ a: (x: string) => void, b: (x: string) => void }>; // string
type T21 = Bar<{ a: (x: string) => void, b: (x: number) => void }>; // string & number
์์ ์์ ๋ ๋๋ฌด ์ด๋ก ์ ์ธ ์์ ์ด๊ณ , ์ข๋ ์ค์ฉ์ ์ธ ์์ ๋ฅผ ๋ค์ ๋ค์ด๋ณด๊ฒ ๋ค.
๋ค์ fn ์ด๋ผ๋ ํจ์๊ฐ ์๋ค๊ณ ํ์.
์ด fn ํจ์๋ ๋งค๊ฐ๋ณ์๋ก number, string, boolean ๋ก ๊ตฌ์ฑ๋ ํ์
์ ๊ฐ์ง๊ณ ์๊ณ , ๋ฆฌํด ํ์
์ string | void ์ ๋์จ ํ์
์ด๋ค.
infer ํค์๋๋ฅผ ์ฌ์ฉํ๋ฉด ์ด ํจ์์ ๋งค๊ฐ๋ณ์ ํ์ ๊ณผ ๋ฆฌํฑ ํ์ ์ ๋ฝ์ ๋ฐํ ํ ์๊ฐ ์๋ค.
function fn(num: number, str: string, bool: boolean): string | void {
return num.toString();
}
type My_ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
type My_Parameters<T extends (...args: any) => any> = T extends (...args: infer R) => any ? R : never;
type Return_Type = My_ReturnType<typeof fn> // ํจ์์ ๋ฆฌํด ํ์
์ ๋ฐํ
// type Return_Type = string | voi
type Parameters_Type = My_Parameters<typeof fn> // ํจ์์ ํ๋ผ๋ฏธํฐ๋ค์ ํ์
์ ๋ฐํ
// type Parameters_Type = [num: number, ste: string, bool: boolean]
const a: My_ReturnType<typeof fn> = 'Hello';
const b: My_Parameters<typeof fn> = [123, 'Hello', true];
์ฐ์ My_ReturnType<T> ๊ฐ ์ด๋ค ์๋ฆฌ๋ก ํจ์์ ๋ฆฌํด ํ์ ๋ง ๋ฝ์ ๋ฐํ ํ ์ ์๋์ง ์์๋ณด์.
๊บพ์ ๊ดํธ <T> ๋ถ๋ถ ์ ๋ค๋ฆญ ๋ถ๋ถ๋ง ์ดํด๋ณธ๋ค๋ฉด, <T extends (...args: any) => any> ์ด ๋ป์ ํ์
ํ๋ผ๋ฏธํฐ T๋ ์ค๋ก์ง ํจ์ ํ์
๋ง ๋ฐ์ ์ ์๋ค๋ ๋ง์ด๋ค. ๊ทธ๋์ ์ ๋ค๋ฆญ ์ธ์์๋ ํจ์๊ฐ ๋ค์ด์จ๋ค.


์ด๋ฅผ ์์ fn ํจ์์ ํ์ ์ ๋น๋์ด๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ด ๋๋ค.


๋ฏธ๋ฆฌ ์ ์๋ ์กฐ๊ฑด๋ถ ํ์
TypeScript 2.8 ๋ฒ์ ๋ถํฐ lib.d.ts์ ๋ฏธ๋ฆฌ ์ ์๋ ์กฐ๊ฑด๋ถ ํ์ (Predefined conditional types)์ ์ถ๊ฐ๋ฌ๋ค.
์์์ ๋ค๋ฃจ์๋ ์กฐ๊ฑด๋ถ ํ์ ์ ์์ฉํด ์ ํธ๋ฆฌํฐ ํ์ ์ฒ๋ผ, ๋ฏธ๋ฆฌ ํฌํผ(helper) ํจ์๋ฅผ ๋ง๋ค์ด ๋์ ๊ฒ์ผ๋ก ๋ณด๋ฉด ๋๋ค.
๋ฏธ๋ฆฌ ์ ์๋ ์กฐ๊ฑด๋ถ ํ์ ์ข ๋ฅ๋ ๋ค์๊ณผ ๊ฐ๋ค.
Exclude<T, U>: U์ ํ ๋นํ ์ ์๋ ํ์ ์ T์์ ์ ์ธ.Extract<T, U>: U์ ํ ๋นํ ์ ์๋ ํ์ ์ T์์ ์ถ์ถNonNullable<T>: T์์ null๊ณผ undefined๋ฅผ ์ ์ธ.ReturnType<T>: T๊ฐ ํจ์์ผ๋, ํจ์ ํ์ ์ ๋ฐํ ํ์ ์ ์ป๊ธฐ.InstanceType<T>: ์์ฑ์ ํจ์ ํ์ ์ ์ธ์คํด์ค ํ์ ์ ์ป๊ธฐ.
type T00 = Exclude<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "b" | "d"
type T01 = Extract<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "a" | "c"
type T02 = Exclude<string | number | (() => void), Function>; // string | number
type T03 = Extract<string | number | (() => void), Function>; // () => void
type T04 = NonNullable<string | number | undefined>; // string | number
type T05 = NonNullable<(() => string) | string[] | null | undefined>; // (() => string) | string[]
function f1(s: string) {
return { a: 1, b: s };
}
class C {
x = 0;
y = 0;
}
type T10 = ReturnType<() => string>; // string
type T11 = ReturnType<(s: string) => void>; // void
type T12 = ReturnType<(<T>() => T)>; // {}
type T13 = ReturnType<(<T extends U, U extends number[]>() => T)>; // number[]
type T14 = ReturnType<typeof f1>; // { a: number, b: string }
type T15 = ReturnType<any>; // any
type T16 = ReturnType<never>; // never
type T17 = ReturnType<string>; // ์ค๋ฅ
type T18 = ReturnType<Function>; // ์ค๋ฅ
type T20 = InstanceType<typeof C>; // C
type T21 = InstanceType<any>; // any
type T22 = InstanceType<never>; // never
type T23 = InstanceType<string>; // ์ค๋ฅ
type T24 = InstanceType<Function>; // ์ค๋ฅ
# ์ฐธ๊ณ ์๋ฃ
https://heropy.blog/2020/01/27/typescript/
https://typescript-kr.github.io/pages/advanced-types.html
์ ๋ก์ด ํ์ ์คํฌ๋ฆฝํธ ์ฌ์ธ์
์ด ๊ธ์ด ์ข์ผ์ จ๋ค๋ฉด ๊ตฌ๋ & ์ข์์
์ฌ๋ฌ๋ถ์ ๊ตฌ๋
๊ณผ ์ข์์๋
์ ์์๊ฒ ํฐ ํ์ด ๋ฉ๋๋ค.