ํด๋น ๋ฌธ์๋ type-challenges ์ ๊ด๋ จํ ๋ด์ฉ์ ๋ด๊ณ ์์ต๋๋ค.
๋ฌธ์ : ๋ฐฐ์ด(ํํ) T๋ฅผ ๋ฐ์ ์ฒซ ์์์ ํ์ ์ ๋ฐํํ๋ ์ ๋ค๋ฆญ First๋ฅผ ๊ตฌํํ์ธ์.
๋ต์:
type First<T extends any[]> = T extends [] ? never : T[0];First๋ผ๋ ํ์ ์ ๋ฐฐ์ด์ ํํ์ด๊ฑฐ๋ ๋ฐฐ์ด๊ณผ ์ ์ฌํ ํํ๋ฅผ ๋ฐ์ ์ ๋๋ฆญ T๋ฅผ ๋ฐ์ต๋๋ค.
์ผํญ์ฐ์ฐ์๋ฅผ ์ด์ฉํด T๊ฐ ๋น์์ ๊ฒฝ์ฐ never ํ์ ์ด๋ฉฐ ๋น์ด์์ง ์์ ๊ฒฝ์ฐ ์ฒซ ์์์ ํ์ ์ ๋ฐํํฉ๋๋ค.
ํน์ ์๋์ ๊ฐ์ด ๋น์ทํ ๋ก์ง์ผ๋ก ๊ตฌ์ฑํ ์ ์์ต๋๋ค.
type First<T extends any[]> = T extends { length: 0 } ? never : T[0];์๋๋ ํ์ง ์์ 14๋ฒ ๋ฌธ์ ์ ๋๋ค.
/* _____________ ์ฌ๊ธฐ์ ์ฝ๋ ์
๋ ฅ _____________ */
type First<T extends any[]> = any;
/* _____________ ํ
์คํธ ์ผ์ด์ค _____________ */
import type { Equal, Expect } from "@type-challenges/utils";
type cases = [
Expect<Equal<First<[3, 2, 1]>, 3>>,
Expect<Equal<First<[() => 123, { a: string }]>, () => 123>>,
Expect<Equal<First<[]>, never>>,
Expect<Equal<First<[undefined]>, undefined>>
];
type errors = [
// @ts-expect-error
First<"notArray">,
// @ts-expect-error
First<{ 0: "arrayLike" }>
];๋ฌธ์ : ๋ฐฐ์ด(ํํ)์ ๋ฐ์ ๊ธธ์ด๋ฅผ ๋ฐํํ๋ ์ ๋ค๋ฆญ Length<T>๋ฅผ ๊ตฌํํ์ธ์.
๋ต์:
type Length<T extends readonly any[]> = T["length"];๋ฐฐ์ด์ ๋ฐ์์ผ ํ๊ธฐ์ <T extends any[]> ๊ฐ ํ์ํฉ๋๋ค.
์ฌ๊ธฐ์ readonly(์ฝ๊ธฐ ์ ์ฉ)๋ฅผ ์ฌ์ฉํ์ง ์์ผ๋ฉด TypeScript๋ ๋ฐฐ์ด์ด ๋ณ๊ฒฝ๋ ์ ์๊ธฐ ๋๋ฌธ์ ํด๋น ๋ฐฐ์ด ๊ธธ์ด์ ๋ํด ์ถ๋ก ์ ํ ์ ์๊ฒ ๋๋ฉฐ ์ด์ ์๋ฌ๊ฐ ๋ฐ์ํฉ๋๋ค.
<T extends readonly any[]>๋ก ๋ณ๊ฒฝํจ์ผ๋ก์จ ํด๋น ๋ฐฐ์ด์ ๋ ์ด์ ๋ณ๊ฒฝ๋ ์ ์๋ ๋ฐฐ์ด์ด๋ฏ๋ก ํด๋น ๋ฐฐ์ด์ ๊ธธ์ด๋ฅผ ์ ํํ๊ฒ ์ถ๋ก ํ ์ ์๊ฒ ๋ฉ๋๋ค.
์ดํ T["length"]๋ฅผ ํตํด ํด๋น ๋ฐฐ์ด์ ๊ธธ์ด๋ฅผ ๋ฐํํฉ๋๋ค.
์๋๋ ํ์ง ์์ 18๋ฒ ๋ฌธ์ ์ ๋๋ค.
/* _____________ ์ฌ๊ธฐ์ ์ฝ๋ ์
๋ ฅ _____________ */
type Length<T> = any;
/* _____________ ํ
์คํธ ์ผ์ด์ค _____________ */
import type { Equal, Expect } from "@type-challenges/utils";
const tesla = ["tesla", "model 3", "model X", "model Y"] as const;
const spaceX = [
"FALCON 9",
"FALCON HEAVY",
"DRAGON",
"STARSHIP",
"HUMAN SPACEFLIGHT",
] as const;
type cases = [
Expect<Equal<Length<typeof tesla>, 4>>,
Expect<Equal<Length<typeof spaceX>, 5>>,
// @ts-expect-error
Length<5>,
// @ts-expect-error
Length<"hello world">
];๋ฌธ์ : T์์ U์ ํ ๋นํ ์ ์๋ ํ์
์ ์ ์ธํ๋ ๋ด์ฅ ์ ๋ค๋ฆญ Exclude<T, U>๋ฅผ ์ด๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ๊ตฌํํ์ธ์.
๋ต์:
type MyExclude<T, U> = T extends U ? never : T;T extends U๋ฅผ ํตํด T์ ๊ฐ ์์๊ฐ U์ ํ ๋น์ด ๊ฐ๋ฅํ์ง๋ฅผ ํ์ธํฉ๋๋ค.
์ผํญ ์ฐ์ฐ์๋ฅผ ํตํด ๋ง์ฝ ๊ฐ๋ฅํ๋ฉด never ํ์
์ ๋ฐํํด ํด๋น ์์๋ฅผ ์ ์ธํ๊ณ ํ ๋น์ด ๊ฐ๋ฅํ์ง ์๋ค๋ฉด ํด๋น ์์๋ฅผ ๊ทธ๋๋ก ๋ฐํํฉ๋๋ค.
์๋๋ ํ์ง ์์ 43๋ฒ ๋ฌธ์ ์ ๋๋ค.
/* _____________ ์ฌ๊ธฐ์ ์ฝ๋ ์
๋ ฅ _____________ */
type MyExclude<T, U> = any;
/* _____________ ํ
์คํธ ์ผ์ด์ค _____________ */
import type { Equal, Expect } from "@type-challenges/utils";
type cases = [
Expect<Equal<MyExclude<"a" | "b" | "c", "a">, "b" | "c">>,
Expect<Equal<MyExclude<"a" | "b" | "c", "a" | "b">, "c">>,
Expect<
Equal<MyExclude<string | number | (() => void), Function>, string | number>
];๋ฌธ์ : Promise์ ๊ฐ์ ํ์ ์ ๊ฐ์ธ์ธ ํ์ ์ด ์์ ๋, ์์ ๊ฐ์ธ์ธ ํ์ ์ด ๋ฌด์์ธ์ง ์ด๋ป๊ฒ ์ ์ ์์๊น์?
๋ต์:
type MyAwaited<T extends { then: unknown }> = Awaited<Promise<T>>;Awaited๋ ํ์ ์คํฌ๋ฆฝํธ์์ ์ ๊ณตํ๋ ์ ํธ๋ฆฌํฐ ํ์ ์ผ๋ก Promise ํ์ ์์ ๊ฐ์ธ์ ธ ์๋ ํ์ ์ ์ถ์ถํฉ๋๋ค.
์๋ฅผ ๋ค์ด, Promise<string>์ ์ฒ๋ฆฌํ ๋ Awaited<Promise<string>>๋ string์ ๋ฐํํฉ๋๋ค.
๋ฐ๋ผ์ ์ด ์ฝ๋์์ Promise๋ฅผ ์ฌ์ฉํ์ผ๋ฏ๋ก, T๊ฐ then ๋ฉ์๋๋ฅผ ๊ฐ์ง ๊ฐ์ฒด๋ผ๋ฉด Promise์ฒ๋ผ ์ฒ๋ฆฌํ๊ณ ๋ด๋ถ์ ํ์ ์ ์ถ์ถํ๊ฒ ๋ฉ๋๋ค.