[TS] ํ์ ์คํฌ๋ฆฝํธ ์ ์ฝ ์กฐ๊ฑด๊ณผ ์กฐ๊ฑด๋ถ ํ์
์๋ณ์ ์์ญ / ํ์ ๊ตฌํ ์์ญ
type
, interface
ํค์๋๋ฅผ ์ฌ์ฉํ ํ์
์ ์ธ์ =
๋ฑํธ์ {}
์ค๊ดํธ๋ฅผ ๊ธฐ์ค์ผ๋ก ์๋ณ์(์ข), ํ์
๊ตฌํ(์ฐ) ์์ญ์ผ๋ก ๊ตฌ๋ถํ ์ ์๋ค.
// type ์๋ณ์ = ํ์
๊ตฌํ
type MyType = string | number;
// interface ์๋ณ์ { ํ์
๊ตฌํ }
interface User {
name: string;
age: number;
}
์ ์ฝ ์กฐ๊ฑด | Constraints
์๋ณ์ ์์ญ์์ ์ฌ์ฉํ๋ extends
๋ ์ ์ฝ ์กฐ๊ฑด์ ์ถ๊ฐํ ์ ์๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก ์ ๋ค๋ฆญ์ ๋ชจ๋ ํ์
์ด ์ฌ ์ ์์ง๋ง ์ ์ฝ ์กฐ๊ฑด์ ์ด์ฉํด ํน์ ํ์
์ผ๋ก ์ ํํ ์ ์๋ค.
๊ธฐ๋ณธ ๋ฌธ๋ฒ :
T extends U
—T
๋U
์ ๋ถ๋ถ ์งํฉ(T ⊆ U
)์ผ๋ก ๋ณผ ์ ์์ex)
64 extends number
: O — 64๋number
์ ๋ถ๋ถ ์งํฉ์ด๋ฏ๋ก
ex)number extends 64
: X — 64๋ณด๋คnumber
๊ฐ ๋ ํฐ ๊ฐ๋ ์ด๋ฏ๋ก
// string, number๋ง ๋ฐ๋๋ก ์ ๋ค๋ฆญ(T) ํ์
์ ์ฝ
interface User<T extends string | number> {
name: string;
age: T;
}
const userA: User<number> = { name: 'Smith', age: 32 }; // OK
const userA: User<string> = { name: 'Smith', age: '32' }; // OK
์ ์ฝ ์กฐ๊ฑด์ ์ด์ฉํด ์ ๋ค๋ฆญ ํ์
์ด ๋ฐฐ์ด์์ ์๋ ค์ค ์ ์๋ค. ์ ์ฝ ์กฐ๊ฑด์ ์ฌ์ฉํ์ง ์์ผ๋ฉด ์ ๋ค๋ฆญ ํ์
(T
)์ด ๋ฐฐ์ด์ธ์ง ํ์
์คํฌ๋ฆฝํธ๋ ์์ง ๋ชปํ๊ธฐ ๋๋ฌธ์ ...T
๊ฐ์ Rest ๋ฌธ๋ฒ์ ์ฌ์ฉํ๋ฉด ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
// ํ์
์์คํ
์ Array.push๋ฅผ ๊ตฌํํ ์์
type Push1<T, U> = [...T, U]; // Error! A rest element type must be an array type
type Push2<T extends unknown[], U> = [...T, U];
type Result = Push2<[1, 2], '3'>; // [1, 2, '3']
์ ๋ค๋ฆญ ํ์
์ length
๊ฐ์ ํน์ ํ๋กํผํฐ๊ฐ ์๋ค๋ ๊ฑธ ์๋ ค์ค ๋๋ ์ ์ฝ ์กฐ๊ฑด์ ์ฌ์ฉํ๋ค. ์ ์ฝ ์กฐ๊ฑด ์์ด ์ฌ์ฉํ๋ฉด ์ ๋ค๋ฆญ ํ์
์ length
ํ๋กํผํฐ๊ฐ ์๋์ง ํ์
์คํฌ๋ฆฝํธ๊ฐ ์์ง ๋ชปํ๊ธฐ ๋๋ฌธ์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
// ์ฃผ์ด์ง ๋ฐฐ์ด์ ๊ธธ์ด๋ฅผ ๋ฐํํ๋ ์ ๋ค๋ฆญ Length
type Length1<T> = T['length']; // Error! Type ‘length’ cannot be used to index type ‘T’
type Length2<T extends { length: number }> = T['length'];
type T0 = Length2<[1, 2, 3]>; // 3
// T๋ฅผ ๋ฐฐ์ด๋ก ์ง์ ํด๋ length ํ๋กํผํฐ๋ฅผ ์ฌ์ฉํ ์ ์๋ค
type Length3<T extends unknown[]> = T['length'];
type T1 = Length3<[1, 2]>; // 2
๐ก ํ์
๋งค๊ฐ๋ณ์์๋ =
๋ฑํธ๋ฅผ ์ฌ์ฉํด ๊ธฐ๋ณธ๊ฐ์ ์ง์ ํ ์ ์๋ค. ์ ๋ค๋ฆญ์ ์ ํ์ ์ผ๋ก ๋ฐ๋ ์ํฉ์์ ์ฌ์ฉํ๋ค. ์๋๋ K
๊ฐ ์ฃผ์ด์ง์ง ์์ ๊ฒฝ์ฐ๋ฅผ ๋๋นํด K
์ ๊ธฐ๋ณธ๊ฐ์ keyof T
๋ก ์ง์ ํ ์์(์ฐธ๊ณ ).
type MyType<T, K extends keyof T = keyof T> = T & { ... }
์กฐ๊ฑด๋ถ ํ์ | Conditional Types
ํ์
๊ตฌํ ์์ญ์์ ์ฌ์ฉํ๋ extends
๋ ์ผํญ ์ฐ์ฐ์๋ฅผ ์ด์ฉํด ์กฐ๊ฑด๋ถ ํ์
์ ์ถ๊ฐํ ์ ์๋ค. ์ ๋ค๋ฆญ์ด ๊ฐ์ง๋ ํ์
์ข
๋ฅ์ ๋ฐ๋ผ(์กฐ๊ฑด์ ๋ฐ๋ผ) ๋ค๋ฅธ ๊ฐ์ ์ง์ ํ ๋ ์ ์ฉํ๋ค.
๊ธฐ๋ณธ ๋ฌธ๋ฒ :
T extends U ? X : Y
—T
๊ฐU
์ ํ ๋น ๊ฐ๋ฅํ๋ฉด(๋ถ๋ถ ์งํฉ์ด๋ฉด)X
, ์๋๋ฉดY
๋ฆฌํด
๐ก T
๊ฐ ์ ๋์จ์ผ ๋ T extends U
๊ตฌ์กฐ๋ฅผ ์ฌ์ฉํ๋ฉด, ์ ๋์จ T
์ ๊ฐ ์์๋ค์ ์ํํ๋ฉด์ ์กฐ๊ฑด ์ ์ฉ
// ์๋ณ์ ์์ญ(์ข)์์ C ํ์
์ boolean์ผ๋ก ์ ํ(์ ์ฝ ์กฐ๊ฑด)
// ํ์
๊ตฌํ ์์ญ(์ฐ)์์ C ํ์
์ด true๋ฉด T ๋ฐํ, false๋ฉด F ๋ฐํ(์กฐ๊ฑด๋ถ ํ์
)
type If<C extends boolean, T, F> = C extends true ? T : F;
type A = If<true, 'a', 'b'>; // 'a'
type B = If<false, 'a', 'b'>; // 'b'
// Exclude ๋ด์ฅ ์ ํธ ํ์
์ ๊ตฌํํ ์์. T๊ฐ U์ ํ ๋น๋ ์ ์๋ ์์๋ง ๋ฐํ
// (T0) T์ 'a'๋ U์ 'a'์ ํ ๋นํ ์ ์์ผ๋ฏ๋ก ์ ์ธ(never)
// (T1) T์ 'a','b'๋ U์ 'a','b'์ ํ ๋นํ ์ ์์ผ๋ฏ๋ก ์ ์ธ(never)
type MyExclude<T, U> = T extends U ? never : T;
type T0 = Exclude<'a' | 'b' | 'c', 'a'>; // "b" | "c"
type T1 = Exclude<'a' | 'b' | 'c', 'a' | 'b'>; // "c"
๋ฐฐ์ด๋ก๋ ์ ๋ค๋ฆญ ํ์
์ T[number]
๋ก ์ ๊ทผํ๋ฉด(์ธ๋ฑ์ค ํ์
) T
๋ฐฐ์ด์ ์๋ ๋ชจ๋ ์์๋ค์ ์ ๋์จ์ ๋ฐํํ๋ค. T
๊ฐ [1, 2, 3]
์ด๋ผ๋ฉด T[number]
๋ 1 | 2 | 3
์ ๋ฐํํ๋ค. ์ธ๋ฑ์ค ํ์
์ด ๋ฐํํ ์ ๋์จ์ ์กฐ๊ฑด๋ถ ํ์
์ ์ฌ์ฉํ๋ฉด ํน์ ๊ฐ์ด ๋ฐฐ์ด ์์์ ํฌํจ๋๋์ง ํ์ธํ ์ ์๋ค. ex) U extends T[number]
// ํ์
์์คํ
์ Array.includes๋ฅผ ๊ตฌํํ ์์
// ์๋ณ์ ์์ญ(์ข)์์ T ํ์
์ ๋ฐฐ์ด๋ก ์ ํ(์ ์ฝ ์กฐ๊ฑด)
// ํ์
๊ตฌํ ์์ญ(์ฐ)์์ U ํ์
์ด T ๋ฐฐ์ด ์์์ ํฌํจ๋๋ค๋ฉด true ๋ฐํ, ์๋๋ฉด false ๋ฐํ(์กฐ๊ฑด๋ถ ํ์
)
type Includes<T extends unknown[], U> = U extends T[number] ? true : false;
type HasD = Includes<['A', 'B', 'C'], 'D'>; // false
T[number]
์ธ๋ฑ์ค ํ์
๊ณผ ์กฐ๊ฑด๋ถ ํ์
์ ์ด์ฉํด ๋ฐฐ์ด์ ์ฒซ๋ฒ์งธ ์์๋ฅผ ๋ฐํํ๋ ์ ํธ๋ฆฌํฐ๋ฅผ ๊ตฌํํ ์ ์๋ค. ๋น ๋ฐฐ์ด์ด ์จ๋ค๋ฉด T[0]
์ ๋์ํ์ง ์๊ธฐ ๋๋ฌธ์ ์กฐ๊ฑด๋ถ ํ์
์ผ๋ก ๋น ๋ฐฐ์ด์ธ์ง ํ์ธํ๊ณ ๋ถ๊ธฐ๋ฅผ ๋๋ ์ผ ํ๋ค.
type First<T extends any[]> = T extends [] ? never : T[0];
type T0 = First<[1, 2, 3]> // 1
type T1 = First<[]> // never
๐ก never
ํ์
์ ์ด๋ ํ ๊ฐ๋ ๊ฐ์ง ์ ์๊ธฐ ๋๋ฌธ์(๋น ํ์
) []
์ never[]
๋ ๋์ผํ๋ค๊ณ ๊ฐ์ฃผํ๋ค.
์กฐ๊ฑด๋ถ ํ์ ์ ์ง์ ํ ๋ ์๋์ฒ๋ผ ์ผํญ ์ฐ์ฐ์๋ฅผ ์ฐ์ํด์ ์ฌ์ฉํ ์ ์๋ค
type MyType<T> =
T extends string ? 'Str' :
T extends number ? 'Num' :
T extends boolean ? 'Boo' :
T extends undefined ? 'Und' :
T extends null ? 'Nul' :
'Obj';
ํ์ ์ถ๋ก | Infer
infer
ํค์๋๋ฅผ ์ฌ์ฉํด ํ์
์ถ๋ก ์ฌ๋ถ๋ฅผ ํ์ธํ ์ ์๋ค. TS ์์ง์ด ํ์
์ ์ถ๋ก ํ ์ ์๋๋ก ํ๊ณ ๊ทธ ๊ฐ์ ์ ๋ค๋ฆญ ํ์
(U
๋ฑ)์ ํ ๋นํ๋ค. infer
ํค์๋๋ ์ ์ฝ ์กฐ๊ฑด extends
๊ฐ ์๋, ์กฐ๊ฑด๋ถ ํ์
extends
์ ์์๋ง ์ฌ์ฉํ ์ ์๊ณ , ์ถ๋ก ํ ๋ณ์๋(์ ๋ค๋ฆญ ํ์
) true
๋ถ๊ธฐ์์๋ง ์ฌ์ฉํ ์ ์๋ค.
๊ธฐ๋ณธ ๋ฌธ๋ฒ :
T extends infer U ? U : T
—U
๊ฐ ์ถ๋ก ๊ฐ๋ฅํ ํ์ ์ด๋ฉดU
๋ฆฌํด, ์๋๋ฉดT
๋ฆฌํด
// R์ ์ ๋ค๋ฆญ์ผ๋ก ๋ฐ์ number๊ฐ ๋๊ณ , number ํ์
์ ์ถ๋ก ํ ์ ์์ผ๋ฏ๋ก R์ ๋ฐํํ๋ค.
// ์ฆ MyType<number>๋ number๋ฅผ ๋ฐํํ๋ฏ๋ก, ๋ณ์ a์ number ํ์
์ธ 888์ ํ ๋นํ ์ ์๋ค.
type MyType<T> = T extends infer R ? R : null;
const a: MyType<number> = 888; // OK
// ํจ์ ํ๋ผ๋ฏธํฐ๋ฅผ ํ์
์ผ๋ก ๋ฐํํ๋ Paramters ๋ด์ฅ ์ ํธ๋ฆฌํฐ ๊ตฌํ ์์
// T๊ฐ ํจ์์ ํํ๊ฐ ์๋๋ผ๋ฉด false ๋ถ๊ธฐ๋ฅผ ํ์ never ๋ฐํ(๋ฌด์)
// T๊ฐ ํจ์์ ํํ๋ผ๋ฉด ํ๋ผ๋ฏธํฐ ํ์
์ ๋งค๊ฐ๋ณ์ R์ ํ ๋นํ๊ณ true ๋ถ๊ธฐ์์ R ๋ฐํ
type Parameters<T> = T extends (...args: infer R) => any ? R : never;
type T0 = Parameters<() => string>; // []
type T1 = Parameters<(s: string) => void>; // [string]
declare function f1(arg: { a: number; b: string }): void;
type T2 = Parameters<typeof f1>; // [{a: number, b: string}]
type T3 = Parameters<string>; // Error! Type 'string' does not satisfy the constraint '(...args: any) => any'
Promise<Type>
์ Type
์ Promise
๋ก ๋ํํ ํ์
์ด๋ค. ๋ฐ๋๋ก Promise
๋ฑ์ผ๋ก ๋ํํ ํ์
์ ์ป์ด๋ด๋ ๊ฒ์ ์ธ๋ํ์ด๋ผ๊ณ ํ๋ค(ํ์
๋ด๋ถ์ ์๋ ํ์
์ ์ป์ด๋ด๋ ๊ฒ). ํ์
์คํฌ๋ฆฝํธ๋ ์กฐ๊ฑด๋ถ ํ์
์ ๋ํ ํ์
์ถ๋ก ์ ์ ๊ณตํ๋ค. ๋ฐ๋ผ์ Promise
๋ก ๊ฐ์ผ ํ์
์ ์ถ๋ก ํ ์ ์๋ค๋ฉด R
๋งค๊ฐ๋ณ์์ ํ ๋น๋๋๋ก ํ ์ ์๋ค. R
๋งค๊ฐ๋ณ์๋ true
๋ถ๊ธฐ(... ? true : false
)์์ ์ฌ์ฉํ ์ ์๋ค.
// TS 4.5์ ์๋ก ์ถ๊ฐ๋ Awaited ์ ํธ๋ฆฌํฐ ํ์
๊ตฌํ ์์
// Promise ๋ด๋ถ์ ์ด๋ค ํ์
์ด ์ฌ์ง ๋ชจ๋ฅด๋ฏ๋ก infer ํค์๋๋ฅผ ์ด์ฉํด ํ์
์ถ๋ก
// T๊ฐ Promise๊ฐ ์๋๋ผ๋ฉด T๋ฅผ ๋ฐํํ๊ณ (false ๋ถ๊ธฐ),
// T๊ฐ Promise๊ณ Promise๋ก ๊ฐ์ผ ํ์
์ ์ถ๋ก ํ ์ ์๋ค๋ฉด R ๋งค๊ฐ๋ณ์์ ์ถ๋ก ํ ํ์
ํ ๋น
// Promise<Promise<string>> ์ฒ๋ผ ๋ค์ค ๋ํํ์ ์ ์์ผ๋ฏ๋ก true ๋ถ๊ธฐ์์ ์ฌ๊ท์ ์ผ๋ก ์ธ๋ํ
type Awaited<T> = T extends Promise<infer R> ? Awaited<R> : T;
type UnWrap1 = Awaited<string>; // string
type UnWrap2 = Awaited<Promise<number>>; // number
T
๊ฐ ๋ฐฐ์ด์ด๋ผ๋ฉด Rest ๋ฌธ๋ฒ๊ณผ infer
ํค์๋๋ฅผ ํจ๊ป ์ฌ์ฉํ ์๋ ์๋ค.
// A, B ์ ๋ค๋ฆญ์ ๋ฐ์ ๋์ผํ ํ์
์ธ์ง ํ์ธํ๋ ์ ํธ๋ฆฌํฐ ํจ์
type Equal<A, B> = A extends B ? (B extends A ? true : false) : false;
type Includes<T extends unknown[], U> = T extends [infer F, ...infer R]
? Equal<F, U> extends true // F์ U๊ฐ ๊ฐ๋ค๋ฉด true ๋ฐํ, ์๋๋ฉด R๊ณผ U๋ฅผ ๋๊ฒจ์ ์ฌ๊ทํธ์ถ
? true
: Includes<R, U>
: false; // T๊ฐ ๋น๋ฐฐ์ด์ด๋ผ๋ฉด false ๋ฐํ
type T0 = Includes<['a', 1, 2, 3], 'a'>; // true
๋ ํผ๋ฐ์ค
- ํ๋์ ๋ณด๋ ํ์ ์คํฌ๋ฆฝํธ(updated)
- Type Challenges Solutions
- Typescript ์ ํธ๋ฆฌํฐ ํด๋์ค ํํค์น๊ธฐ
- TypeScript ํ์ ์ ์ ์ฝ๊ธฐ - ๋ช ๊ฐ์ง๋ง ์๋ฉด ์ฌ์์
๊ธ ์์ ์ฌํญ์ ๋ ธ์ ํ์ด์ง์ ๊ฐ์ฅ ๋น ๋ฅด๊ฒ ๋ฐ์๋ฉ๋๋ค. ๋งํฌ๋ฅผ ์ฐธ๊ณ ํด ์ฃผ์ธ์
'๐ช Programming' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[React] ๋ฆฌ์กํธ Suspense ํบ์๋ณด๊ธฐ (0) | 2024.05.06 |
---|---|
[Git] ์๋ฉด ์ ์ฉํ GitHub ๋จ์ถํค / ํ (0) | 2024.05.05 |
[HTML/CSS] select ํ๊ทธ์ ํ์ดํ ์์ด์ฝ ๋ณ๊ฒฝํ๊ธฐ (0) | 2024.05.05 |
[React] ๋ฆฌ์กํธ Strict Mode ์๊ฒฉ ๋ชจ๋์ ์ฌ์ด๋ ์ดํํธ (0) | 2024.05.05 |
[React] ํค๋ณด๋๋ก ์กฐ์ํ ์ ์๋ ๋๋กญ๋ค์ด ์๋์์ฑ ๊ฒ์์ฐฝ ๊ตฌํํ๊ธฐ (0) | 2024.05.05 |
๋๊ธ
์ด ๊ธ ๊ณต์ ํ๊ธฐ
-
๊ตฌ๋
ํ๊ธฐ
๊ตฌ๋ ํ๊ธฐ
-
์นด์นด์คํก
์นด์นด์คํก
-
๋ผ์ธ
๋ผ์ธ
-
ํธ์ํฐ
ํธ์ํฐ
-
Facebook
Facebook
-
์นด์นด์ค์คํ ๋ฆฌ
์นด์นด์ค์คํ ๋ฆฌ
-
๋ฐด๋
๋ฐด๋
-
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
-
Pocket
Pocket
-
Evernote
Evernote
๋ค๋ฅธ ๊ธ
-
[React] ๋ฆฌ์กํธ Suspense ํบ์๋ณด๊ธฐ
[React] ๋ฆฌ์กํธ Suspense ํบ์๋ณด๊ธฐ
2024.05.06 -
[Git] ์๋ฉด ์ ์ฉํ GitHub ๋จ์ถํค / ํ
[Git] ์๋ฉด ์ ์ฉํ GitHub ๋จ์ถํค / ํ
2024.05.05 -
[HTML/CSS] select ํ๊ทธ์ ํ์ดํ ์์ด์ฝ ๋ณ๊ฒฝํ๊ธฐ
[HTML/CSS] select ํ๊ทธ์ ํ์ดํ ์์ด์ฝ ๋ณ๊ฒฝํ๊ธฐ
2024.05.05 -
[React] ๋ฆฌ์กํธ Strict Mode ์๊ฒฉ ๋ชจ๋์ ์ฌ์ด๋ ์ดํํธ
[React] ๋ฆฌ์กํธ Strict Mode ์๊ฒฉ ๋ชจ๋์ ์ฌ์ด๋ ์ดํํธ
2024.05.05