
객체의 키와 값을 서로 바꾸는 타입을 구현하세요.
제약사항
예시
Flip<{ a: "x"; b: "y"; c: "z" }>; // {x: "a", y: "b", z: "c"}
Flip<{ a: 1; b: 2; c: 3 }>; // {1: "a", 2: "b", 3: "c"}
Flip<{ a: false; b: true }>; // {false: "a", true: "b"}
접근 방식
코드
type Flip<T> = { [K in keyof T as T[K] extends PropertyKey ? T[K] : never]: K };
실패 이유
접근 방식
PropertyKey로 제한하는 대신, string, number, boolean 타입을 키 값으로 사용할 수 있도록 제한코드
type Flip<T> = {
[K in keyof T as T[K] extends string | number | boolean
? `${T[K]}`
: never]: K;
};
코드 설명
T[K] extends string | number | boolean 형태로 키 값을 제한숫자 T를 입력받아 해당하는 피보나치 수를 반환하는 제네릭 타입 Fibonacci<T>를 구현하세요.
수열은 다음과 같이 시작됩니다:
1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ...
예시
type Result1 = Fibonacci<3>; // 2
type Result2 = Fibonacci<8>; // 21
접근 방식
코드
type Fibonacci<
T extends number,
Fibo1 extends any[] = ["f"],
Fibo2 extends any[] = ["f"],
Count extends any[] = ["f", "f", "f"]
> = T extends 1 | 2
? 1
: Count["length"] extends T
? [...Fibo1, ...Fibo2]["length"]
: Fibonacci<T, Fibo2, [...Fibo1, ...Fibo2], [...Count, "f"]>;
코드 설명
T extends 1 | 2 형태로 초기 조건 설정(T가 1, 2일 때 항상 1)T가 3 이상일 때 Count의 length가 T와 같아지면 앞의 두 배열을 합한 배열의 length를 반환Count의 length가 T보다 작으면, 뒤의 배열을 앞의 배열에 할당하고, 뒤의 배열은 앞의 배열과 뒤의 배열을 합친 배열을 할당Count에 "f"를 추가하여 재귀 호출문자열 S의 문자들을 최대 한 번씩만 사용하여 만들 수 있는 모든 문자열 조합을 반환하는 AllCombinations<S> 타입을 구현하세요.
예시
type AllCombinations_ABC = AllCombinations<"ABC">;
// 결과값: '' | 'A' | 'B' | 'C' | 'AB' | 'AC' | 'BA' | 'BC' | 'CA' | 'CB' | 'ABC' | 'ACB' | 'BAC' | 'BCA' | 'CAB' | 'CBA'
접근 방법
코드
type StringToTuple<S extends String> = S extends `${infer First}${infer Last}`
? [First, ...StringToTuple<Last>]
: [];
type StringToUnion<S extends string> = StringToTuple<S>[number];
type Permutation<T extends string[], K = T> = [T] extends [never]
? []
: K extends K
? [K, ...Permutation<Exclude<T, K>>]
: never;
type Join<T extends string[]> = T extends [
infer First extends string,
...infer Rest extends string[]
]
? `${First}${Join<Rest>}`
: "";
type AllCombinations<
S extends string,
P = Permutation<StringToUnion<S>>
> = P extends P ? Join<P> : never;
코드 설명
StringToTuple 함수는 문자열을 튜플로 변환StringToUnion 함수는 튜플을 union으로 변환Permutation 함수는 주어진 배열의 순열을 생성Join 함수는 배열을 문자열로 결합실패 이유
Permutation을 활용하면 안됨ABC의 경우 ABC, ACB, BAC, BCA, CAB, CBA 이렇게 6개의 요소만 확인 가능Exclude를 활용해 접근하는 방식은 맞을 듯코드
type StringToUnion<S extends string> = S extends `${infer L}${infer R}`
? L | StringToUnion<R>
: S;
type Combination<A extends string, B extends string> =
| A
| B
| `${A}${B}`
| `${B}${A}`;
type UnionCombination<A extends string, B extends string = A> = A extends B
? Combination<A, UnionCombination<Exclude<B, A>>>
: never;
type AllCombinations<S extends string> = UnionCombination<StringToUnion<S>>;
코드 설명
StringToUnion 함수는 문자열을 union으로 변환 ('' 포함)Combination 함수는 두 문자열을 이용해 조합 생성UnionCombination 함수는 string union으로 들어온 A를 순회하며, 각 요소와 해당 요소를 제외한 union을 재귀적으로 호출하여 조합 생성AllCombinations 함수는 UnionCombination 함수를 활용하여 모든 문자열 조합을 반환
StringToUnion함수 구현 방식
type StringToUnion<S extends string> = S extends `${infer L}${infer R}`
? L | StringToUnion<R>
: S;
이 챌린지에서는 T > U와 같은 GreaterThan<T, U> 타입을 구현해야 합니다.
음수는 고려하지 않아도 됩니다.
예시
GreaterThan<2, 1>; //true가 되어야 함
GreaterThan<1, 1>; //false가 되어야 함
GreaterThan<10, 100>; //false가 되어야 함
GreaterThan<111, 11>; //true가 되어야 함
접근 방법
코드
type StringToTuple<S extends String> = S extends `${infer First}${infer Last}`
? [First, ...StringToTuple<Last>]
: [];
// N 크기의 unknown[] 생성
type BuildArray<
N extends number,
Arr extends unknown[] = []
> = Arr["length"] extends N ? Arr : BuildArray<N, [...Arr, unknown]>;
// T가 U 이상인지 확인(같거나 더 클 경우)
type CompareDigit<T extends number, U extends number> = BuildArray<T> extends [
...BuildArray<U>,
...infer Rest
]
? true
: false;
// 맨 앞의 0을 날려줘야 함
type StringToNumber<S extends string> =
S extends `${"0"}${infer Rest extends number}`
? Rest
: S extends `${infer N extends number}`
? N
: never;
// string[]을 합쳐 string으로 변환
type Join<T extends string[]> = T extends [
infer First extends string,
...infer Rest extends string[]
]
? `${First}${Join<Rest>}`
: "";
type GreaterThan<
T extends number,
U extends number,
TupleT extends string[] = StringToTuple<`${T}`>,
TupleU extends string[] = StringToTuple<`${U}`>
> =
// 같은 값인지 비교
T extends U
? false
: // 두 숫자의 자릿수가 같은지 비교
TupleT["length"] extends TupleU["length"]
? TupleT["length"] extends 1
? // 자릿수가 모두 1일 경우, 한자리수 비교
CompareDigit<T, U>
: // 실제 앞에서부터 한글자씩 비교 로직
TupleT extends [
infer TFirst extends string,
...infer TRest extends string[]
]
? TupleU extends [
infer UFirst extends string,
...infer URest extends string[]
]
? TFirst extends UFirst
? GreaterThan<
StringToNumber<Join<TRest>>,
StringToNumber<Join<URest>>
>
: CompareDigit<StringToNumber<TFirst>, StringToNumber<UFirst>>
: true
: false
: // 자릿수가 다를 경우, length들끼리 비교
CompareDigit<TupleT["length"], TupleU["length"]>;
코드 설명
같은 값일 경우 false 리턴
이후 두 숫자의 자릿수가 같은지 비교
자릿수가 같고 한자리수일 경우, 두 숫자를 비교하여 결과 리턴
자릿수가 같고 한자리수가 아닐 경우, 재귀로 비교(앞의 한 자리씩)
자릿수가 다를 경우, 각 자릿수를 비교하여 결과 리턴
StringToTuple 함수는 문자열을 튜플로 변환
BuildArray 함수는 숫자에 따라 그 길이만큼의 unknown[] 타입을 생성
CompareDigit 함수는 두 숫자를 비교하여 결과 리턴
StringToNumber 함수는 문자열을 숫자로 변환
Join 함수는 튜플을 문자열로 변환
이 챌린지에서는 Zip<T, U> 타입을 구현해야 합니다. 여기서 T와 U는 반드시 Tuple 이어야 합니다.
예시
type exp = Zip<[1, 2], [true, false]>; // expected to be [[1, true], [2, false]]
문제 설명
접근 방법
코드
type Zip<T extends any[], U extends any[]> = T extends [
infer TFirst,
...infer TRest
]
? U extends [infer UFirst, ...infer URest]
? [[TFirst, UFirst], ...Zip<TRest, URest>]
: []
: [];
코드 설명
IsTuple이라는 타입을 구현하세요. 이 타입은 입력 타입 T를 받아서 T가 튜플 타입인지 여부를 반환합니다.
예시
type case1 = IsTuple<[number]>; // true
type case2 = IsTuple<readonly [number]>; // true
type case3 = IsTuple<number[]>; // false
문제 설명
접근 방법
코드
type IsTuple<T> = [T] extends [never]
? false
: T extends readonly any[]
? number extends T["length"]
? false
: true
: false;
코드 설명