우리는 가끔 숫자 범위에 제한을 두고 싶다...
Sometimes we want to limit the range of numbers...
// ver 1
type NumberRangeImplement<L extends number, H extends number,Flag extends boolean=false,Arr extends any[]=[]>=
H extends Arr['length']?Arr['length']
:Flag extends true?Arr['length']|NumberRangeImplement<L,H,true,[...Arr,1]>
:L extends Arr['length']? Arr['length']|NumberRangeImplement<L,H,true,[...Arr,1]>
:NumberRangeImplement<L,H,false,[...Arr,1]>
// ver 2
type NumberRangeImplement<L extends number, H extends number,Flag extends boolean=false,Arr extends any[]=[],Result extends number[]=[]>=
H extends Arr['length']?Result[number]|Arr['length']
:Flag extends true?NumberRangeImplement<L,H,true,[...Arr,1],[...Result,Arr['length']]>
:L extends Arr['length']? NumberRangeImplement<L,H,true,[...Arr,1],[...Result,Arr['length']]>
:NumberRangeImplement<L,H,false,[...Arr,1]>
type NumberRange<L extends number, H extends number> = NumberRangeImplement<L,H>
우선 사용처에서 구현용 제네릭을 사용하지 못하게 하기 위해 구현과 실제 타입을 분리했다.
ver 1은 제네릭을 순환해서 반환하다보니 H가 49이상 이면 무한 재귀 에러에 걸리게 되었다.
ver 1의 문제점을 해결하고자, Result라는 제네릭을 만들어
그 안에 해당하는 값을 다 넣은 후,
마지막에 Result[number]를 반환해 호출하는 형식으로 구현하였다
type Utils<L, C extends any[] = [], R = L> =
C['length'] extends L
? R
: Utils<L, [...C, 0], C['length'] | R>
type NumberRange<L, H> = L | Exclude<Utils<H>, Utils<L>>
신선한 풀이이다
우선 Utils를 통해 0부터 특정한 값까지의 유니온을 만든다
ex)L이 10이라면 0|1|...|10
이후 L과 H의 Utils를 만들어 Utils<H>에서 Utils<L>를 제외한 값에다 L을 더해준다.
ex) 3에서 5라면
1|2|3|4|5에서 1|2|3을 제외하고 3을 더해주는 형식
https://github.com/type-challenges/type-challenges/issues/9988