View on GitHub: https://tsch.js.org/9898
Find the elements in the target array that appear only once. For example:input: [1,2,2,3,3,4,5,6,6,6]
,ouput: [1,4,5]
.
접근 방식
코드
type IsEqual<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y
? 1
: 2
? true
: false;
type IsUniqueInArray<
T extends any[],
E,
CountArr extends unknown[] = []
> = T extends [infer First, ...infer Rest]
? IsEqual<First, E> extends true
? IsUniqueInArray<Rest, E, [...CountArr, unknown]>
: IsUniqueInArray<Rest, E, CountArr>
: CountArr["length"] extends 1
? true
: false;
type FindEles<
T extends any[],
Original extends any[] = T,
Result extends any[] = []
> = T extends [infer First, ...infer Rest]
? IsUniqueInArray<Original, First> extends true
? FindEles<Rest, Original, [...Result, First]>
: FindEles<Rest, Original, Result>
: Result;
코드 설명
isEqual
함수를 사용View on GitHub: https://tsch.js.org/9989
With type CountElementNumberToObject
, get the number of occurrences of every item from an array and return them in an object.
예시
type Simple1 = CountElementNumberToObject<[]>; // return {}
type Simple2 = CountElementNumberToObject<[1, 2, 3, 4, 5]>;
// return {
// 1: 1,
// 2: 1,
// 3: 1,
// 4: 1,
// 5: 1
// }
type Simple3 = CountElementNumberToObject<[1, 2, 3, 4, 5, [1, 2, 3]]>;
// return {
// 1: 2,
// 2: 2,
// 3: 2,
// 4: 1,
// 5: 1
// }
접근 방식
flatten
처리result
에 해당 요소가 존재하는지 확인value
의 카운트만 증가, 없을 경우에는 새로운 레코드 추가코드
type Flatten<T extends any[]> = T extends [infer First, ...infer Rest]
? First extends any[]
? [...Flatten<First>, ...Flatten<Rest>]
: [First, ...Flatten<Rest>]
: [];
type GetResult<T extends Record<string, unknown[]>> = {
[K in keyof T]: T[K]["length"];
};
type AddResult<
T extends PropertyKey,
Result extends Record<string, unknown[]>
> = {
[K in keyof Result]: K extends `${T}` ? [...Result[K], unknown] : Result[K];
} & (`${T}` extends keyof Result ? {} : { [K in `${T}`]: [unknown] });
type GetCountElement<
T extends any[],
Result extends Record<string, unknown[]> = {}
> = T extends [infer First, ...infer Rest]
? [First] extends [never]
? GetCountElement<Rest, Result>
: First extends PropertyKey
? GetCountElement<Rest, AddResult<First, Result>>
: GetCountElement<Rest, Result>
: GetResult<Result>;
type CountElementNumberToObject<T extends any[]> = GetCountElement<Flatten<T>>;
코드 설명
flatten
처리never
처리를 위해 [First] extends [never]
처리result
에 해당 요소가 존재하는지 확인value
의 카운트 추가(unknown[]
), 없을 경우에는 새로운 레코드 추가GetResult
타입을 통해 객체로 반환실패 이유
코드
type Flatten<T extends any[]> = T extends [infer First, ...infer Rest]
? First extends any[]
? [...Flatten<First>, ...Flatten<Rest>]
: [First, ...Flatten<Rest>]
: [];
type Count<T, R extends Record<string | number, any[]> = {}> = T extends [
infer F extends string | number,
...infer L
]
? F extends keyof R
? Count<L, Omit<R, F> & Record<F, [...R[F], 0]>>
: Count<L, R & Record<F, [0]>>
: {
[K in keyof R]: R[K]["length"];
};
type CountElementNumberToObject<T extends any[]> = [T] extends [[never]]
? {}
: Count<Flatten<T>>;
코드 설명
flatten
처리infer
를 활용해 F
를 string | number
타입으로 제한F
가 keyof R
에 존재하는지 확인Count<L, Omit<R, F> & Record<F, [...R[F], 0]>>
처리F
를 제외한 객체를 만들고, F
를 키로 하고 값을 [...R[F], 0]
으로 하는 객체를 만들어 합침 (count 증가)Count<L, R & Record<F, [0]>>
처리R & Record<F, [0]>
는 R
에서 F
를 키로 하고, 값을 [0]
으로 하는 객체T
순회를 마치면 [K in keyof R]: R[K]["length"]
타입을 통해 객체로 반환View on GitHub: https://tsch.js.org/10969
Please complete type Integer<T>
, type T
inherits from number
, if T
is an integer return it, otherwise return never
.
never
반환접근 방식
코드
type IsAllZero<T extends string> = T extends `${infer First}${infer Rest}`
? First extends "0"
? IsAllZero<Rest>
: false
: true;
type Integer<T> = [T] extends [number]
? number extends T
? never
: `${T}` extends `${infer _Int}.${infer Float}`
? IsAllZero<Float> extends true
? T
: never
: T
: never;
코드 설명
[T] extends [number]
, number extends T
)${T}
extends ${infer _Int}.${infer Float}
)IsAllZero<Float> extends true
)never
반환View on GitHub: https://tsch.js.org/16259
Please complete type ToPrimitive<T>
, type T
inherits from object
, convert T
to a primitive type.
예시
type X = {
name: "Tom";
age: 30;
married: false;
addr: {
home: "123456";
phone: "13111111111";
};
};
type Expected = {
name: string;
age: number;
married: boolean;
addr: {
home: string;
phone: string;
};
};
접근 방식
코드
type InferType<T> = T extends string
? string
: T extends number
? number
: T extends boolean
? boolean
: T extends (...args: any[]) => any
? Function
: T extends any[]
? ChangeArray<T>
: T extends object
? { [K in keyof T]: InferType<T[K]> }
: T;
type ChangeArray<T extends any[]> = {
[K in keyof T]: InferType<T[K]>;
};
type ChangeObject<T> = T extends (...args: any[]) => any
? Function
: T extends any[]
? ChangeArray<T>
: T extends object
? { [K in keyof T]: InferType<T[K]> }
: T;
type ChangeValue<T> = T extends string
? string
: T extends number
? number
: T extends boolean
? boolean
: T;
type ToPrimitive<T extends object> = T extends [...infer R]
? InferType<R>
: {
[K in keyof T]: T[K] extends object
? ChangeObject<T[K]>
: InferType<T[K]>;
};
코드 설명
객체의 프로퍼티를 돌면서 기본 타입으로 변환
기본 타입일 primitive 타입으로 반환
배열/객체일 경우 재귀적으로 처리
그런데 중복된 로직이 많은 것 같아서 하나씩 다 걷어내봄
코드
type PrimitiveType<T> = T extends string
? string
: T extends number
? number
: T extends boolean
? boolean
: T extends (...args: any[]) => any
? Function
: T extends any[] | object
? { [K in keyof T]: PrimitiveType<T[K]> }
: T;
type ToPrimitive<T extends object> = { [K in keyof T]: PrimitiveType<T[K]> };
View on GitHub: https://tsch.js.org/17973
Please complete type DeepMutable<T>
, type T
inherits from object
, convert T
to a mutable object.
예시
type X = {
readonly a: () => 1;
readonly b: string;
readonly c: {
readonly d: boolean;
readonly e: {
readonly g: {
readonly h: {
readonly i: true;
readonly j: "s";
};
readonly k: "hello";
};
};
};
};
type Expected = {
a: () => 1;
b: string;
c: {
d: boolean;
e: {
g: {
h: {
i: true;
j: "s";
};
k: "hello";
};
};
};
};
접근 방식
코드
type isNotPureObject<T extends object> = T extends [...infer _]
? true
: T extends () => {}
? true
: false;
type DeepMutable<T extends object> = {
-readonly [K in keyof T]: T[K] extends object
? isNotPureObject<T[K]> extends false
? DeepMutable<T[K]>
: T[K]
: T[K];
};
코드 설명
View on GitHub: https://tsch.js.org/18142
Returns true if all elements of the list are equal to the second parameter passed in, false if there are any mismatches.
예시
type Test1 = [1, 1, 1];
type Test2 = [1, 1, 2];
type Todo = All<Test1, 1>; // should be same as true
type Todo2 = All<Test2, 1>; // should be same as false
접근 방식
코드
type MyEqual<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y
? 1
: 2
? true
: false;
type All<T extends any[], U> = T extends [infer First, ...infer Rest]
? MyEqual<First, U> extends true
? All<Rest, U>
: false
: true;
코드 설명