FE/type-challenge

21106. Combs

최토피 2023. 10. 10. 12:00
728x90

문제

  1. Combine multiple modifier keys, but the same modifier key combination cannot appear.
  1. In the ModifierKeys provided, the priority of the previous value is higher than the latter value; that is, cmd ctrl is OK, but ctrl cmd is not allowed.

cases

type ModifierKeys = ['cmd', 'ctrl', 'opt', 'fn']
type CaseTypeOne = 'cmd ctrl' | 'cmd opt' | 'cmd fn' | 'ctrl opt' | 'ctrl fn' | 'opt fn'

type cases = [
  Expect<Equal<Combs<ModifierKeys>, CaseTypeOne>>,
]

문제 링크

정답

type Combs<T extends any[]> = T extends [infer T1 extends string, ...infer RestT extends string[]]
  ? RestT['length'] extends 0
    ? never
    : `${T1} ${RestT[number]}` | Combs<RestT>
  : never

풀이

조건

  1. 앞에서 순서대로 2개씩 조합을 한다.
  1. 아이템은 순서대로 우선순위가 있어, 결과물도 우선순위에 따라 배치가 되어야 한다.

해설

우선순위에 따라 결과물의 배치에는 순서가 있으므로, 앞에서 순차적으로 접근하여 조합하도록 한다.

따라서 다음과 같이 순서대로 조합을 얻어내고, 나머지 배열은 재귀적으로 접근하여 결과물을 얻을 수 있도록 한다.

type Combs<T extends any[]> = T extends [infer T1 extends string, ...infer RestT extends string[]]
    ? RestT['length'] extends 0
        ? never
        : Modify<T1, RestT> | Combs<RestT>
    : never

Modify는 조합을 얻어내는 타입으로 다음과 같이 구현할 수 있다.

type Modify<T extends string, Candidates extends string[]>
    = Candidates extends [infer C1 extends string, ...infer Rest extends string[]]
    ? `${T} ${C1}` | Modify<T, Rest>
    : never

이 둘을 조합하면 다음과 같다.

type Combs<T extends any[]> = T extends [infer T1 extends string, ...infer RestT extends
    ? RestT['length'] extends 0
        ? never
        : Modify<T1, RestT> | Combs<RestT>
    : never
type Modify<T extends string, Candidates extends string[]>
    = Candidates extends [infer C1 extends string, ...infer Rest extends string[]]
    ? `${T} ${C1}` | Modify<T, Rest>
    : never

 

리팩토링

Modify는 다음과 같이 코드를 줄일 수 있다.

type Modify<T extends string, Candidates extends string[]> 
	= `${T} ${Candidates[number]}`

이를 Combs에 바로 적용하면 코드를 더 줄일 수 있다.

type Combs<T extends any[]> = T extends [infer T1 extends string, ...infer RestT extends string[]]
  ? RestT['length'] extends 0
    ? never
    : `${T1} ${RestT[number]}` | Combs<RestT>
  : never

 


 

혹시 오류나 개선점이 있다면 댓글 부탁드립니다.

728x90