[TS] Type-Challenges 스터디 17주차
![[TS] Type-Challenges 스터디 17주차](/_next/image?url=https%3A%2F%2Fvelog.velcdn.com%2Fimages%2Fhayou%2Fpost%2F653e86db-be9c-4888-be56-5590c7ac8109%2Fimage.jpg&w=3840&q=75)
[medium] 26401. JSON Schema to TypeScript
View on GitHub: https://tsch.js.org/26401
문제
Implement the generic type JSONSchema2TS which will return the TypeScript type corresponding to the given JSON schema.
Additional challenges to handle:
- additionalProperties
- oneOf, anyOf, allOf
- minLength and maxLength
문제 설명
- 주어진 JSON Schema를 TypeScript 타입으로 변환하는 문제
- 추가 챌린지
- additionalProperties
- oneOf, anyOf, allOf
- minLength and maxLength
시도 1
접근 방식
- string, number, boolean은 그대로 반환
- enum일 경우 해체
- object일 경우 재귀
- array일 경우 재귀
- object의 경우 required, readonly 등 처리
코드
type JSONSchema2TS<T> = T extends { enum: infer E extends readonly any[] }
? E[number]
: T extends { type: "string" }
? string
: T extends { type: "number" }
? number
: T extends { type: "boolean" }
? boolean
: T extends { type: "object" }
? T extends { properties: infer P }
? T extends { required: readonly (infer R extends string)[] }
? {
[K in Extract<keyof P, R[number]>]: JSONSchema2TS<P[K]>;
} & {
[K in Exclude<keyof P, R[number]>]?: JSONSchema2TS<P[K]>;
}
: {
[K in keyof P]?: JSONSchema2TS<P[K]>;
}
: Record<string, unknown>
: T extends { type: "array" }
? T extends { items: infer I }
? JSONSchema2TS<I>[]
: unknown[]
: never;
코드 설명
enum타입일 경우,E[number]형태로 반환string,number,boolean타입일 경우 그대로 반환object타입일 경우,properties와required를 처리, 이후 재귀array타입일 경우, 재귀로 처리
[medium] 27133. Square
View on GitHub: https://tsch.js.org/27133
문제
Implement the generic type Square<T> which will return the square of the given number.
문제 설명
- 주어진 숫자의 제곱을 반환하는 문제
시도 1
접근 방식
0이 있을 경우 제외하고 계산(나중에00으로 계산)- 절대값 처리
- 제곱 길이만큼의 배열 활용
코드
type Abs<N extends number> = `${N}` extends `-${infer R extends number}`
? R
: N;
type SplitZeroes<
N extends number,
Z extends string = ""
> = `${N}` extends `${infer N extends number}0`
? SplitZeroes<N, `${Z}00`>
: [N, Z];
type SquareTuple<
N extends number,
A extends any[] = [],
Acc extends any[] = []
> = A["length"] extends N
? [...A, ...Acc]
: SquareTuple<N, [1, ...A], [...A, ...A, ...Acc]>;
type Square<
_N extends number,
N extends [number, string] = SplitZeroes<_N>,
U extends any[] = SquareTuple<Abs<N[0]>>
> = `${U["length"]}${N[1]}` extends `${infer N extends number}` ? N : never;
코드 설명
Abs<N[0]>: 절대값 처리SplitZeroes<_N>:0제외 처리 (나중에00형태로 추가 것임)SquareTuple<Abs<N[0]>>: 제곱 길이만큼의 배열 생성- 해당 결과를 바탕으로 조합하여 제곱 결과 반환
[medium] 27152. Triangular Number
View on GitHub: https://tsch.js.org/27152
문제
Implement the generic type Square<T> which will return the square of the given number.
문제 설명
- 1부터 N까지의 합을 반환하는 문제
시도 1
접근 방식
- Array를 활용하여 1부터 N까지 증가하는 배열 생성
- 해당 배열의 길이의 합을 반환하는 로직 생성
코드
type NArr<
N extends number,
Result extends unknown[] = []
> = Result["length"] extends N ? Result : NArr<N, [...Result, unknown]>;
type Triangular<
N extends number,
FirstArr extends unknown[] = NArr<N>,
Result extends unknown[] = []
> = FirstArr["length"] extends 0
? Result["length"]
: FirstArr extends [infer _, ...infer Rest]
? Triangular<N, Rest, [...Result, ...FirstArr]>
: never;
코드 설명
NArr<N>: 1부터N까지 증가하는 배열 생성FirstArr: 최초N의 크기의 배열 생성, 이후 1개씩 요소 삭제Result:FirstArr의 요소의 누적 합 배열
[medium] 27862. Cartesian Product
View on GitHub: https://tsch.js.org/27862
문제
Given 2 sets (unions), return its Cartesian product in a set of tuples.
예시
CartesianProduct<1 | 2, "a" | "b">;
// [1, 'a'] | [2, 'a'] | [1, 'b'] | [2, 'b']
문제 설명
- 두 개의 집합을 받아 카티시안 곱을 반환하는 문제
시도 1
접근 방식
- 두 개의 집합을 전체 순회하며 튜플 형태로 반환
코드
type CartesianProduct<T, U, TT = T, UU = U> = T extends TT
? U extends UU
? [T, U]
: never
: never;
코드 설명
T extends TT:T의 요소를 하나씩 순회U extends UU:U의 요소를 하나씩 순회[T, U]: 튜플 형태로 반환- 순회해서 생긴 튜플들은
|로 구분되어 반환됨
[medium] 27932. Merge All
View on GitHub: https://tsch.js.org/27932
문제
Merge variadic number of types into a new type. If the keys overlap, its values should be merged into an union.
예시
type Foo = { a: 1; b: 2 };
type Bar = { a: 2 };
type Baz = { c: 3 };
type Result = MergeAll<[Foo, Bar, Baz]>; // expected to be { a: 1 | 2; b: 2; c: 3 }
문제 설명
- 가변 인자의 타입을 하나의 타입으로 병합
- 키가 겹칠 경우 값을 합치는(union) 문제
시도 1
접근 방식
T extends T꼴로 각 요소를 순회하며 키를 확인- 만약에 키가
result에 존재하면 해당 키의 값을 머지 - 만약에 키가
result에 존재하지 않으면 해당 키의 값을 추가
코드
type MergeAll<XS extends any[], Result = {}> =
XS extends [infer First, ...infer Rest]
? { [Key in keyof Result]: Key extends keyof First ? Result[Key] | First[Key] : Result[Key] }.. 어쩌구
: Result
실패 이유
- 조건문이 너무 많이 들어가고, 명확하게 코드 진행이 되지 않는 느낌
- 다른 방식으로 해결하고자 접근방식 변경
시도 2
접근 방식
- 기존 Merge 로직 사용
T extends [infer First, ...infer Rest]꼴로 각 요소를 순회하며 키를 확인- 해당 요소를 Merge 처리해주고, 이후 재귀로 처리
코드
type Merge<F, S> = {
[K in keyof F | keyof S]: K extends keyof F
? K extends keyof S
? F[K] | S[K]
: F[K]
: K extends keyof S
? S[K]
: never;
};
type MergeAll<T extends object[], Result = {}> = T extends [
infer First extends object,
...infer Rest extends object[]
]
? MergeAll<Rest, Merge<Result, First>>
: Result;
코드 설명
Merge<Result, First>: 현재 요소와 이전 결과를 Merge 처리 (기존에 사용하던 Merge 로직 참고, 단 유니온 처리)MergeAll<Rest, Merge<Result, First>>: 이후 재귀로 처리Result: 최종 결과
[medium] 27958. Check Repeated Tuple
View on GitHub: https://tsch.js.org/27958
문제
Implement type CheckRepeatedChars<T> which will return whether type T contains duplicated member
예시
type CheckRepeatedTuple<[1, 2, 3]> // false
type CheckRepeatedTuple<[1, 2, 1]> // true
문제 설명
- 튜플에 중복된 요소가 있는지 확인하는 문제
시도 1
접근 방식
- 전체 요소 순회 후, 각 요소를 비교하여 중복된 요소가 있는지 확인
코드
type IsEqual<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y
? 1
: 2
? true
: false;
type IsRepeat<T extends unknown[], El, Cnt extends unknown[] = []> = T extends [
infer First,
...infer Rest
]
? IsEqual<First, El> extends true
? IsRepeat<Rest, El, [...Cnt, unknown]>
: IsRepeat<Rest, El, Cnt>
: Cnt["length"] extends 1
? false
: true;
type CheckRepeatedTuple<T extends unknown[]> = T extends [
infer First,
...infer Rest
]
? IsRepeat<T, First> extends true
? true
: CheckRepeatedTuple<Rest>
: false;
코드 설명
IsEqual<X, Y>: 두 요소가 같은지 확인IsRepeat<T, First>: 현재 요소와 이전 결과를 비교하여 중복된 요소가 있는지 확인(전체 요소에 존재하는 현재 요소의 개수가 1개인지 확인)CheckRepeatedTuple<T>: 전체 요소를 순회하며 중복된 요소가 있는지 확인, 중복된 요소가 있으면true, 없으면 다음 요소 확인
comments
loading…