타입 챌린지 9989 - Count Element Number To Object

소파의 벨로그·2025년 5월 16일

타입챌린지

목록 보기
85/131

문제 링크

문제

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를 구현했다.

방식은 다음과 같다.

  1. {나오는 요소 : 나온 횟수 만큼의 length를 갖는 배열}을 반환하는 타입을 만든다.(CountElementNumberToObjectTupled)
    • 맨 첫 번째 요소로 만든 {나오는 요소 : 나온 횟수 만큼의 length를 갖는 배열}과 그 뒤에 있는 요소들로 만든 {나오는 요소 : 나온 횟수 만큼의 length를 갖는 배열}을 합친다(Merge)
    • 이때 맨 첫 번째 요소로 {나오는 요소 : 나온 횟수 만큼의 length를 갖는 배열}을 만들기 위해 배열여부를 따진다.
      배열이라면, 1을 반복해 나온 값이 대상이 된다.
      배열이 아니라면, {요소:[1]}이 대상이 된다
  2. 1에서 만든 배열을 {나오는 요소 : 나온 횟수}로 파싱해서 반환한다(ParsedTuppledMap)

다른 사람의 풀이

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

0개의 댓글