일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- microsoft azure openai
- HTTP
- 회고록
- 코딩테스트
- 월간cs
- node.js
- 해커톤
- 2024년 회고록
- configmodule
- 타입스크립트
- typeorm
- 회고
- npm
- network
- type-safe configservice
- 타입 챌린지
- 와글와글
- equal 타입
- 굿바이 2024년
- 타입챌린지
- TypeScript 타입챌린지
- 백엔드
- nestjs
- configservice
- 스터디
- TypeScript
- 이펙티브 타입스크립트
- type challenge equal type
- Type Challenge
- typescript type challenge
- Today
- Total
iamkanguk.dev
[타입챌린지-MEDIUM] 5153: IndexOf 본문
문제
https://github.com/iamkanguk97/type-challenges/blob/main/questions/05153-medium-indexof/README.md
풀이
/* _____________ Your Code Here _____________ */
/* _____________ Test Cases _____________ */
import type { Equal, Expect } from '@type-challenges/utils'
type IndexOf<T, U, L extends unknown[] = []>
= T extends [infer A, ...infer B]
? Equal<A, U> extends true ? L['length'] : IndexOf<B, U, [...L, A]>
: -1
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>>,
Expect<Equal<IndexOf<[string, 'a'], 'a'>, 1>>,
Expect<Equal<IndexOf<[any, 1], 1>, 1>>,
]
풀이 해설
아예 생각지도 못했다. 진짜 내가 많이 부족하다고 느꼈다.
필자는 배열을 순회해야겠다 싶었는데 전혀 다른 풀이법이었다.
당분간은 지금까지 풀었던 타입 챌린지를 복습하면서 타입스크립트 공식문서도 틈틈이 읽어봐야 할 것 같다.
다른 분들의 풀이를 보면 이해가 정말 쉽게 된다. 항상 느끼는데 왜 문제를 보면 이런 풀이법이 떠오르지 않을까 싶다 ㅠ 많은 노력을 해야겠다.
- type IndexOf<T, U, L extends unknown[] = []>: 문제에서는 T와 U만 있었을 것이다. 하지만 우리는 제네릭 L을 추가할 것인데, 타입은 배열 타입이고 Default는 빈 배열이다.
- T extends [infer A, ...infer B] ? <> : -1: 일단 크게 한번 보자. T 배열을 A 원소 1개와, 나머지 원소들을 합친 B 배열로 나눌 수 있다면 <>를 실행하고, 그렇지 않으면 -1을 반환한다는 것이다. -1을 반환한다는 것은 원소를 못찾았을 경우를 의미한다. 해당 설명만 보면 으이? 할 수 있는데 아래 설명도 같이 보면 이해가 될 것이라고 생각한다.
- (위의 괄호) Equal<A, U> extends true ? L['length'] : IndexOf<B, U, [...L, A]>: 제일 핵심 부분이다!!
- Equal<A, U>: 문제에서 제공하는 util 라이브러리를 사용하였다. 사용하지 않을 것이라면 직접 Equal 타입을 구현해도 무방하다. 여기서 A는 위에서 배열을 두개로 나눌 때 첫 원소를 의미한다. 그리고 U는 문제에서 찾으려고 하는 값이다.
- extends true ? L['length'] : IndexOf<B, U, [...L, A]>
- Equal의 결과가 true이면 L의 길이를 반환하고, 그렇지 않으면 IndexOf를 재귀적으로 실행한다는 것이다.
- 이 때, IndexOf에 B, U, [...L, A]를 넣는데 한번 살펴보자.
- B는 위에서 나눈 배열을 의미한다.
- U는 문제에서 찾으려고 하는 값 그대로 넣으면 된다.
- [...L, A] 는 비교한 값들을 누적한다는 의미이다.
일단 코드적으로만 해석해서 설명해봤는데 아마 잘 이해가 될 지는 모르겠다. 그런데 머리속으로 생각하면 그렇게 어렵지 않다.
딱 한마디로만 정의하면 "L에다가 기전에 비교한 값들 A를 누적하는 것이다. 현재값인 A가 U랑 일치하면 L 배열의 길이가 A의 인덱스이기 때문에 그대로 반환하면 된다."
예시를 하나 들어서 설명해보겠다. 테스트 케이스는 2번째 케이스를 사용하겠다.
<First Step>
- T = [2, 6, 3, 8, 4, 1, 7, 3, 9] // U = 3 // L = []
- T extends [infer A, ...infer B] >>> A: 2, B: [6, 3, 8, 4, 1, 7, 3, 9] >>> 나눌 수 있기 때문에 <> 진행 (위에 <> 에요!)
- Equal<A, U> extends true ? L['length'] : IndexOf<B, U, [...L, A]>
-- Equal<A, U>: A(2)와 U(3)은 같지 않기 때문에 False. 따라서 조건에 의해 IndexOf 부분을 실행한다.
-- IndexOf<B, U, [...L, A]>: B = [6, 3, 8, 4, 1, 7, 3, 9] // U = 3 // [...L, A] = [2]
<Second Step>
- T = [6, 3, 8, 4, 1, 7, 3, 9] // U = 3 // L = [2]
- T extends [infer A, ...infer B] >>> A: 6, B: [3, 8, 4, 1, 7, 3, 9] >>> 나눌 수 있기 때문에 <> 진행 (위에 <> 에요!)
- Equal<A, U> extends true ? L['length'] : IndexOf<B, U, [...L, A]>
-- Equal<A, U>: A(6)와 U(3)은 같지 않기 때문에 False. 따라서 조건에 의해 IndexOf 부분을 실행한다.
-- IndexOf<B, U, [...L, A]>: B = [3, 8, 4, 1, 7, 3, 9] // U = 3 // [...L, A] = [2, 6]
<Third Step>
- T = [3, 8, 4, 1, 7, 3, 9] // U = 3 // L = [2, 6]
- T extends [infer A, ...infer B] >>> A: 3, B: [8, 4, 1, 7, 3, 9] >>> 나눌 수 있기 때문에 <> 진행 (위에 <> 에요!)
- Equal<A, U> extends true ? L['length'] : IndexOf<B, U, [...L, A]>
-- Equal<A, U>: A(3)와 U(3)은 서로 같기 때문에 L['length']를 반환한다!
-- 따라서 현재 L['length']는 2이기 때문에 2가 반환되고, 실제로 3은 index가 2인 것을 확인할 수 있다.
<2023-04-10 추가>
5317번 LastIndexOf 라는 문제가 있는데 비슷하게 풀어볼 수 있으니까 한번 풀어보길 바란다!
'Type Challenge' 카테고리의 다른 글
[Type Challenge - MEDIUM] Chainable Options (0) | 2024.10.02 |
---|---|
[Type Challenge] Omit 문제에 대한 고찰 (readonly 관련) (0) | 2024.09.27 |
[타입챌린지-MEDIUM] 9: Deep Readonly (0) | 2024.04.04 |
[타입챌린지-MEDIUM] 8: Readonly 2 (0) | 2024.03.27 |
[타입챌린지-MEDIUM] 3: Omit (0) | 2024.03.24 |