FE/type-challenge

5153. IndexOf

최토피 2023. 8. 17. 18:42
728x90

문제

Implement the type version of Array.indexOf, indexOf<T, U> takes an Array T, any U and returns the index of the first U in Array T.

type Res = IndexOf<[1, 2, 3], 2>; // expected to be 1
type Res1 = IndexOf<[2,6, 3,8,4,1,7, 3,9], 3>; // expected to be 2
type Res2 = IndexOf<[0, 0, 0], 2>; // expected to be -1

cases

type cases = [
  Expect<Equal<IndexOf<[1, 2, 3], 2>, 1>>,
  Expect<Equal<IndexOf<[2, 6, 3, 8, 4, 1, 7, 3, 9], 3>, 2>>,
  Expect<Equal<IndexOf<[0, 0, 0], 2>, -1>>,
  Expect<Equal<IndexOf<[string, 1, number, 'a'], number>, 2>>,
  Expect<Equal<IndexOf<[string, 1, number, 'a', any], any>, 4>>,
]

문제 링크

 

정답

type IndexOf<T, U, V extends number[] = []> = T extends [infer T1, ...infer Rest]
  ? (<W>() => W extends T1 ? 0 : 1) extends (<W>() => W extends U ? 0 : 1)
      ? V['length']
      : IndexOf<Rest, U, [...V, 0]>
  : -1

풀이

조건

  1. 두 번째 인자의 위치를 반환한다.
  1. 없는 경우 -1을 반환한다.

해설

재귀적으로 검사하는 로직을 설계한다.

type IndexOf<T, U, V extends number[] = []> = 
	T extends [infer T1, ...infer Rest]
    ? T1 extends U 
			? V['length'] 
			: IndexOf<Rest, U, [...V, 0]>
    : -1

네번째 case와 같은 3 extends number 등의 경우에 의도치 않은 결과가 나오므로, 양방향으로 extends를 하는지 확인한다.

type IndexOf<T, U, V extends number[] = []> = 
	T extends [infer T1, ...infer Rest]
	  ? [T1, U] extends [U, T1] 
			? V['length'] 
			: IndexOf<Rest, U, [...V, 0]>
	  : -1

다섯번째 case와 같이 any에 문제가 생기는 경우가 발생한다. 따라서 Equal 처럼 함수화해서 비교하는 방식으로 해결한다.

type IndexOf<T, U, V extends number[] = []> = T extends [infer T1, ...infer Rest]
  ? (<W>() => W extends T1 ? 0 : 1) extends (<W>() => W extends U ? 0 : 1)
      ? V['length']
      : IndexOf<Rest, U, [...V, 0]>
  : -1
사실 <W>() => W extends U ? 0 : 1 부분은 잘 이해가 가지 않는다.
어째서 두 함수를 비교하는 것으로 Equality가 보장되는거지? 아시는 분은 댓글 부탁드려요 ㅜ

혹시 오류나 개선점이 있다며 댓글 부탁드립니다 :)

728x90