프로그래밍/TypeScript
달과 일자로 이루어진 MMDD 타입
카카수(kakasoo)
2024. 3. 17. 23:17
반응형
최초의 풀이와 오답
type Int = '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '0';
type February = '02'
type MonthsHasDays30 = '04' | '06' | '09' | '11';
type MonthsHasDays31 = '01' | '03' | '05' | '07' | '08' | '10' | '12';
type Months = February | MonthsHasDays30 | MonthsHasDays31;
type Days = Exclude<`${0 | 1 | 2}${Int}` | '30' | '31', '00'>
type DaysByMonth<T extends Months> =
T extends February
? Exclude<Days, '29' | '30' | '31'>
: T extends MonthsHasDays30
? Exclude<Days, '30'>
: Days
type ValidDate<T extends string> =
T extends `${infer Month extends Months}${infer Days}`
? Days extends DaysByMonth<Month>
? true
: false
: false;
31일로 이루어진 달들을 체크하고, 30일로 이루어진 달들을 체크한다.
2월은 윤년을 제외하면 28일까지만 있는 것이 일반적이기 때문에 달에 따라서 일자가 달라지게끔 DaysByMonth
타입을 정의한다.
DaysByMonth
는 제네릭으로 받은 달(=Month) T
에 따라 01부터 31까지 존재하는 Days에서 불가능한 날짜를 Exclude
한다.
DaysByMonth
가 완성되었다면 문제에서 구현하라고 하는 ValidDate
타입을 구현하면 된다.
ValidDate
는 인자로 받은 제네릭 T
를 Month와 Days로 구성되어 있는 문자열로 나누고 Days가 Month에 맞는지 검사한다.
문제는 나뉘어진 Month가, 예를 들어 '0101' 라면 '01' 일수도 있고 '10' 일 수도 있는 상황이 된다.
정답 풀이법
type Int = '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '0';
type February = '02'
type MonthsHasDays30 = '04' | '06' | '09' | '11';
type MonthsHasDays31 = '01' | '03' | '05' | '07' | '08' | '10' | '12';
type Months = February | MonthsHasDays30 | MonthsHasDays31;
type Days = Exclude<`${0 | 1 | 2}${Int}` | '30' | '31', '00'>
type Decimal = `${Int}${Int}`;
type DaysByMonth<T extends February | MonthsHasDays30 | MonthsHasDays31> =
T extends February
? Exclude<Days, '29' | '30' | '31'>
: T extends MonthsHasDays30
? Exclude<Days, '30'>
: Days
type AllDays = {
[M in Months]: `${M}${DaysByMonth<M>}`
}[Months]
type ValidDate<T extends string> = T extends AllDays ? true : false;
따라서 더 쉽게 풀기 위해서 일단 AllDays라는, '0101'부터 '1231'까지의 가능한 모든 날짜를 타입으로 만들고,
제네릭 인자 T가 그 날짜 중 하나인지를 검사하게 바꾼다.
반응형