[TS] TypeScript ํ์ ์คํฌ๋ฆฝํธ Infer ํค์๋ ํ์ฉํ๊ธฐ
ํ์
์คํฌ๋ฆฝํธ infer
๋ ํ์
์ ์ถ๋ก ํ๋๋ฐ ์ฌ์ฉํ๋ ํค์๋๋ค. ๋ฐฐ์ด ์์ ํ์
, ํจ์ ํ๋ผ๋ฏธํฐ ํ์
, ํจ์ ๋ฐํ ํ์
๋ฑ ํน์ ๋ฌธ๋งฅ์ ํ์
์ถ์ถ์ด ํ์ํ ๋ infer
๋ฅผ ํ์ฉํ ์ ์๋ค.
๊ธฐ๋ณธ ๋ฌธ๋ฒ :
T extends infer U ? U : T
—U
๊ฐ ์ถ๋ก ๊ฐ๋ฅํ ํ์ ์ด๋ฉดU
๋ฆฌํด, ์๋๋ฉดT
๋ฆฌํด
infer
๋ ํ์
๊ตฌํ ์์ญ(ํ ๋น ์ฐ์ฐ์ ์ฐ์ธก)์ ์กฐ๊ฑด๋ถ ํ์
(extends
์ )์์๋ง ์ฌ์ฉํ ์ ์์ผ๋ฉฐ, TS ์์ง์ด ํ์
์ ์ถ๋ก ํ๊ณ ๋ณ์(์ ๋ค๋ฆญ ํ์
)์ ํ ๋นํ๋ค. ํ ๋น๋ ๋ณ์๋ ์กฐ๊ฑด๋ถ ํ์
์ true
๋ถ๊ธฐ์์๋ง ์ฌ์ฉํ ์ ์๋ค.
// Error! 'infer' declarations are only permitted in the 'extends' clause of a conditional type.(ts1338)
type Wrong1<T extends (infer U)[]> = T[0]; // ์ ์ฝ ์กฐ๊ฑด extends์ ์ฌ์ฉํด์ ์๋ฌ
type Wrong2<T> = (infer U)[] extends T ? U : T; // extends ์กฐ๊ฑด์ ์ฌ์ฉํ์ง ์์์ ์๋ฌ
// Error! Cannot find name 'U'.(ts2304)
type Wrong3<T> = T extends (infer U)[] ? T : U; // false ๋ถ๊ธฐ์ ์ฌ์ฉํด์ ์๋ฌ
UnpackedArray
๋ฐฐ์ด ์์ ํ์ ์ถ์ถ
T
๊ฐ ๋ฐฐ์ด์ด๊ณ , ๋ฐฐ์ด ์์์ ํ์
์ ์ถ๋ก ํ ์ ์์ผ๋ฉด U
(์ ๋ค๋ฆญ ํ์
) ๋ณ์์ ํ ๋นํ๋ค. โผ
type UnpackedArray<T> = T extends (infer U)[] ? U : T;
type T0 = string[];
type U0 = UnpackedArray<T0>; // string
UnpackedFn
ํจ์ ๋ฐํ ํ์ ์ถ์ถ
T
๊ฐ ํจ์์ด๊ณ , ํจ์์ ๋ฐํ ํ์
์ ์ถ๋ก ํ ์ ์์ผ๋ฉด ๋ณ์(์ ๋ค๋ฆญ ํ์
) U
์ ํ ๋นํ๋ค. โผ
type UnpackedFn<T> = T extends (...args: unknown[]) => infer U ? U : T;
type T1 = () => string;
type U1 = UnpackedFn<T1>; // string
ํจ์๋ฅผ ์ค๋ฒ๋ก๋ํ๋ค๋ฉด ๋ง์ง๋ง ํธ์ถ ์๊ทธ๋์ฒ๋ฅผ ํ์ ์ถ๋ก ์ ์ฌ์ฉํ๋ค. ์ฐธ๊ณ ๋ก ์๊ทธ๋์ฒ(Signiture)๋ ํจ์๋ ๋ฉ์๋์ ์ ๋ ฅ(ํ๋ผ๋ฏธํฐ)๊ณผ ์ถ๋ ฅ(๋ฐํ๊ฐ)์ ๋ํ ํ์ ์ ๋ณด๋ฅผ ์๋ฏธํ๋ค.
declare function foo(x: string): number;
declare function foo(x: number): string;
declare function foo(x: string | number): string | number;
type U2 = UnpackedFn<typeof foo>; // string | number
Unpacked
๋ฐฐ์ด ์์ ํ์ / ํจ์ ๋ฐํ ํ์ / ํ๋ก๋ฏธ์ค ๊ฒฐ๊ณผ ํ์ ์ถ์ถ
T
๊ฐ ๋ฐฐ์ด | ํจ์ | ํ๋ก๋ฏธ์ค๊ฐ ์๋๋ฉด T
๋ฅผ ๊ทธ๋๋ก ๋ฐํํ๋ค. โผ
type Unpacked<T> =
T extends (infer U)[] ? U :
T extends (...args: any[]) => infer U ? U :
T extends Promise<infer U> ? U :
T; // ์ ๋ฌ๋ฐ์ T ๊ทธ๋๋ก ๋ฐํ
type T0 = Unpacked<string>; // string
type T1 = Unpacked<string[]>; // string
type T2 = Unpacked<() => string>; // string
type T3 = Unpacked<Promise<string>>; // string
type T4 = Unpacked<Promise<string>[]>; // Promise<string>
type T5 = Unpacked<Unpacked<Promise<string>[]>>; // string
PropertyType
๊ฐ์ฒด ํค ํ์ ์ถ์ถ
T
๊ฐ ๊ฐ์ฒด์ด๊ณ , ๊ฐ์ฒด ํค ํ์
์ ์ถ๋ก ํ ์ ์์ผ๋ฉด ๋ณ์(์ ๋ค๋ฆญ ํ์
) U
, R
์ ํ ๋นํ๋ค. โผ
type User = { id: number; name: string };
type PropertyType<T> = T extends { id: infer U; name: infer R } ? [U, R] : T;
type U3 = PropertyType<User>; // [number, string]
๋ง์ฝ ์ ๋ค๋ฆญ ํ์
U
๋ฅผ 1๊ฐ๋ง ์ ์ธํ๋ฉด ์ ๋์จ ํ์
์ ๋ฐํํ๋ค. ๊ณต๋ณ ์์น(ํจ์ ํ๋ผ๋ฏธํฐ๋ฅผ ์ ์ธํ ๊ณณ)์์ ๋์ผํ ํ์
๋ณ์(U
)์ ๋ํ ํ๋ณด๊ฐ ์ฌ๋ฌ๊ฐ๋ฉด ์ต์ข
ํ์
์ ์ ๋์จ ํ์
์ผ๋ก ์ ์ถํ๊ธฐ ๋๋ฌธ์ด๋ค.
type PropertyType<T> = T extends { id: infer U; name: infer U } ? U : T;
type U4 = PropertyType<User>; // string | number
๋ฐ๋ฉด, ๋ฐ๊ณต๋ณ ์์น(ํจ์ ํ๋ผ๋ฏธํฐ)์์ ๋์ผํ ํ์
๋ณ์(U
)์ ๋ํ ํ๋ณด๊ฐ ์ฌ๋ฌ๊ฐ๋ฉด ์ต์ข
ํ์
์ ์ธํฐ์น์
ํ์
์ผ๋ก ์ ์ถํ๋ค. ๋๋ฌธ์ ์๋ ์์์์ U
๋ string & number
ํ์
์ด ๋๋ค. ํ์ง๋ง ์ ๋ค๋ฆญ์ผ๋ก ๋๊ธด ๋ ๋ฉ์๋์ x
ํ๋ผ๋ฏธํฐ ํ์
๊ณผ ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ false
๋ถ๊ธฐ๋ฅผ ํ์ never
๋ฅผ ๋ฐํํ๋ค. (T extends U ? X : Y
์กฐ๊ฑด๋ถ ํ์
๋ฌธ๋ฒ์์ T
๋ฅผ U
์ ํ ๋นํ ์ ์์ผ๋ฉด true
๋ถ๊ธฐ๋ฅผ, ํ ๋นํ ์ ์์ผ๋ฉด false
๋ถ๊ธฐ๋ฅผ ํ๋ค)
type Bar<T> = T extends { a: (x: infer U) => void; b: (x: infer U) => void }
? U
: never;
type U5 = Bar<{ a: (x: string) => void; b: (x: number) => void }>; // never
๋ ์์ธํ ๋ด์ฉ์ ํ์ ์คํฌ๋ฆฝํธ์ ๊ณต๋ณ์ฑ / ๋ฐ๊ณต๋ณ์ฑ / ์ด๋ณ์ฑ ํฌ์คํ ์ฐธ๊ณ
- ๊ณต๋ณ์ฑ : ์ํผ ํ์
(๋์ ํ์
)์ด ์๋ธ ํ์
(์ข์ ํ์
)์ ์ปค๋ฒํ๋ ๊ด๊ณ
- ์๋ธ ํ์ ์ ์ํผ ํ์ ์ ๋์ ํ ์ ์์ e.g. superType = subType
- ํ์ ์คํฌ๋ฆฝํธ ๊ธฐ๋ณธ ๋์
- ๋ฐ๊ณต๋ณ์ฑ : ์๋ธ ํ์
(์ข์ ํ์
)์ด ์ํผ ํ์
(๋์ ํ์
)์ ์ปค๋ฒํ๋ ๊ด๊ณ
- ์ํผ ํ์ ์ ์๋ธ ํ์ ์ ๋์ ํ ์ ์์ e.g. subType = superType
- ํจ์ ํ๋ผ๋ฏธํฐ ๋์
- ์ด๋ณ์ฑ : ๊ณต๋ณ์ฑ๊ณผ ๋ฐ๊ณต๋ณ์ฑ์ ๋ชจ๋ ํฌํจํ๋ ๊ด๊ณ
- ์ํผ ํ์ ๊ณผ ์๋ธ ํ์ ์ ๋ชจ๋ ๋์ ํ ์ ์์
strictFunctionTypes
์ต์ ์ ๊ป์ ๋ ํจ์ ํ๋ผ๋ฏธํฐ ๋์
FirstIfString
๋ฐฐ์ด์ ์ฒซ๋ฒ์งธ ์์๊ฐ ๋ฌธ์์ด ํ์ ์ด๋ฉด ์ถ์ถ
์๋ ์์์ ์ฒซ๋ฒ์งธ ์กฐ๊ฑด๋ถ ํ์
์์ ์ ๋ค๋ฆญ์ผ๋ก ๋ฐ์ T
๊ฐ ๋ฐฐ์ด์ธ์ง ํ์ธํ๊ณ , ๋ฐฐ์ด์ ์ฒซ๋ฒ์งธ ์์๋ฅผ ํ์
๋ณ์ S
์ ํ ๋นํ๋ค. ๋๋ฒ์งธ ์กฐ๊ฑด๋ถ ํ์
์์ ํ ๋น๋ ํ์
๋ณ์ S
๊ฐ ๋ฌธ์์ด์ธ์ง ํ์ธํ๊ณ ์ฐธ์ด๋ฉด S
๋ฅผ ๋ฐํํ๋ค.
type FirstIfString<T> = T extends [infer S, ...unknown[]] // ์ฒซ๋ฒ์งธ ์กฐ๊ฑด๋ถ ํ์
? S extends string // ๋๋ฒ์งธ ์กฐ๊ฑด๋ถ ํ์
? S
: never
: never;
type A = FirstIfString<[string, number, number]>; // string
type B = FirstIfString<['a', number, number]>; // 'a'
type C = FirstIfString<['a | b', number]>; // 'a' | 'b'
ํ์
์คํฌ๋ฆฝํธ 4.7 ๋ฒ์ ๋ถํฐ infer
ํ์
์ extends
์ ์ ์ฌ์ฉํด์ ์ ์ฝ ์กฐ๊ฑด์ ์ถ๊ฐํ ์ ์๋ค. ์ ์์์์ 2๊ฐ์ ์กฐ๊ฑด๋ถ ํ์
์ ์ฌ์ฉํ๋๋ฐ, ์ด ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ฉด 1๊ฐ์ ์กฐ๊ฑด๋ถ ํ์
๋ง ์ฌ์ฉํด์ ์์ฑํ ์ ์๋ค.
// infer์ extends๋ฅผ ์ฌ์ฉํด์ ํ์
๋ณ์ S๋ฅผ ๋ฌธ์์ด ํ์
์ผ๋ก ์ ํํ๊ณ ์๋ค
type FirstIfString<T> = T extends [infer S extends string, ...unknown[]]
? S
: never;
UnionToIntersection
์ ๋์จ ํ์ ์ ๋ฐ์ ์ธํฐ์น์ ํ์ ์ผ๋ก ์ถ์ถ
U
ํ์
๊ฐ ๋ฉค๋ฒ์ ํจ์ ํ์
์ ์์ฑํ๊ณ , ๊ฐ ํจ์ ํ์
์ ํ๋ผ๋ฏธํฐ๋ฅผ ์ถ๋ก ํ์ฌ ์ธํฐ์น์
ํ์
์ ์์ฑํ๋ ์์. โผ
type UnionToIntersection<U> = (
U extends any ? (arg: U) => void : never // ์ฒซ๋ฒ์งธ ์กฐ๊ฑด๋ถ ํ์
) extends (arg: infer R) => void // ๋๋ฒ์งธ ์กฐ๊ฑด๋ถ ํ์
? R
: never;
type T6 = { a: 'a' } | { b: 'b' };
type T7 = UnionToIntersection<T6>; // { a: 'a' } & { b: 'b' }
- ์ฒซ๋ฒ์งธ ์กฐ๊ฑด๋ถ ํ์
:
U extends any ? (arg: U) => void : never
- ํ์
๋ณ์
U
๊ฐ ์ด๋ค ํ์ ์ด๋ ์๊ด์์ด(arg: U) => void
ํ์ ์ผ๋ก ํ์ฅ - ํ์
๋ณ์
U
์ ๊ฐ ๋ฉค๋ฒ์ ๋ํด(arg: U) => void
ํ์ ์ ๊ฐ์ง ์ ๋์จ ๋ฐํ(arg: { a: "a" }) => void | (arg: { b: "b" }) => void
- ํ์
๋ณ์
- ๋๋ฒ์งธ ์กฐ๊ฑด๋ถ ํ์
:
(...) extends (arg: infer R) => void ? R : never
- ํจ์ ํ๋ผ๋ฏธํฐ ํ์
R
์ถ๋ก - ๋ฐ๊ณต๋ณ ์์น์์ ํ์
๋ณ์(
R
)์ ํ๋ณด๊ฐ ์ฌ๋ฌ๊ฐ์ด๋ฏ๋ก ์ธํฐ์น์ ํ์ ๋ฐํ
- ํจ์ ํ๋ผ๋ฏธํฐ ํ์
๋ ํผ๋ฐ์ค
๊ธ ์์ ์ฌํญ์ ๋ ธ์ ํ์ด์ง์ ๊ฐ์ฅ ๋น ๋ฅด๊ฒ ๋ฐ์๋ฉ๋๋ค. ๋งํฌ๋ฅผ ์ฐธ๊ณ ํด ์ฃผ์ธ์
'๐ช Programming' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Express] req.query vs req.params (0) | 2024.05.19 |
---|---|
[JS] ํจ์ํ / ๊ฐ์ฒด ์งํฅ ํ๋ก๊ทธ๋๋ฐ์ ๋ฎ์ ๊ผด (0) | 2024.05.19 |
[JS] JavaScript ์๋ฐ์คํฌ๋ฆฝํธ Map ๋ ์ ์ฌ์ฉํ๊ธฐ (0) | 2024.05.19 |
[CS] ๋๊ธฐ / ๋น๋๊ธฐ, ๋ธ๋กํน / ๋ ผ๋ธ๋กํน (0) | 2024.05.18 |
[JS] ์ ๊ท์์ ๊ทธ๋ฃนํ(Grouping) / ์บก์ฒํ(Capturing) ํ์ฉํ๊ธฐ (0) | 2024.05.18 |
๋๊ธ
์ด ๊ธ ๊ณต์ ํ๊ธฐ
-
๊ตฌ๋
ํ๊ธฐ
๊ตฌ๋ ํ๊ธฐ
-
์นด์นด์คํก
์นด์นด์คํก
-
๋ผ์ธ
๋ผ์ธ
-
ํธ์ํฐ
ํธ์ํฐ
-
Facebook
Facebook
-
์นด์นด์ค์คํ ๋ฆฌ
์นด์นด์ค์คํ ๋ฆฌ
-
๋ฐด๋
๋ฐด๋
-
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
-
Pocket
Pocket
-
Evernote
Evernote
๋ค๋ฅธ ๊ธ
-
[Express] req.query vs req.params
[Express] req.query vs req.params
2024.05.19 -
[JS] ํจ์ํ / ๊ฐ์ฒด ์งํฅ ํ๋ก๊ทธ๋๋ฐ์ ๋ฎ์ ๊ผด
[JS] ํจ์ํ / ๊ฐ์ฒด ์งํฅ ํ๋ก๊ทธ๋๋ฐ์ ๋ฎ์ ๊ผด
2024.05.19 -
[JS] JavaScript ์๋ฐ์คํฌ๋ฆฝํธ Map ๋ ์ ์ฌ์ฉํ๊ธฐ
[JS] JavaScript ์๋ฐ์คํฌ๋ฆฝํธ Map ๋ ์ ์ฌ์ฉํ๊ธฐ
2024.05.19 -
[CS] ๋๊ธฐ / ๋น๋๊ธฐ, ๋ธ๋กํน / ๋ ผ๋ธ๋กํน
[CS] ๋๊ธฐ / ๋น๋๊ธฐ, ๋ธ๋กํน / ๋ ผ๋ธ๋กํน
2024.05.18