CountElementNumberToObject로, 배열에 있는 모든 아이템의 발생 수를 얻어 객체에 넣어 반환하라
With type CountElementNumberToObject, get the number of occurrences of every item from an array and return them in an object.
type TargetType=PropertyKey|PropertyKey[]|TargetType[]
type Merge<T extends Record<any,any[]>,U extends Record<any,any[]>>=
{[R in keyof T|keyof U]:
R extends keyof T?
R extends keyof U?[...T[R],...U[R]]
:T[R]
:U[R]
}
type CountElementNumberToObjectTupled<T extends TargetType[]> =
T extends [infer First , ...infer Rest extends TargetType[]]?
[First] extends [never]?{}
:Merge<
First extends TargetType[]?
CountElementNumberToObjectTupled<First>
:First extends PropertyKey?{[R in First]:[1]}:never
,CountElementNumberToObjectTupled<Rest>>
:{}
type ParsedTuppledMap<T extends Record<any, any[]>>={
[R in keyof T]: T[R]['length']
}
type CountElementNumberToObject<T extends TargetType[]>=ParsedTuppledMap<CountElementNumberToObjectTupled<T>>
우선 사용처에서 구현용 제네릭을 사용하지 못하게 하기 위해 구현과 실제 타입을 분리했다.
그리고, 중첩적인 타입을 제네릭과 mapped type의 key에 넣을 수 있게 TargetType를 구현했다.
방식은 다음과 같다.
type Flatten<T,R extends any[] = []> =
T extends [infer F,...infer L]?
[F] extends [never]?
Flatten<L,R>:
F extends any[]?
Flatten<L,[...R,...Flatten<F>] >
:Flatten<L,[...R,F]>
:R
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
> =
Count<Flatten<T>>
배열을 수평화해서, 수평화한 값을 세는 코드이다.
https://github.com/type-challenges/type-challenges/issues/28355