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:
접근 방식
코드
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
타입일 경우, 재귀로 처리View on GitHub: https://tsch.js.org/27133
Implement the generic type Square<T>
which will return the square of the given number.
접근 방식
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]>>
: 제곱 길이만큼의 배열 생성View on GitHub: https://tsch.js.org/27152
Implement the generic type Square<T>
which will return the square of the given number.
접근 방식
코드
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
의 요소의 누적 합 배열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']
접근 방식
코드
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]
: 튜플 형태로 반환|
로 구분되어 반환됨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 }
접근 방식
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
실패 이유
접근 방식
T extends [infer First, ...infer Rest]
꼴로 각 요소를 순회하며 키를 확인코드
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
: 최종 결과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
접근 방식
코드
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
, 없으면 다음 요소 확인