# type-challenges
# 17・Currying 1
type Curry<T> =
T extends (...args:infer A)=>infer R?
A extends [infer F,...infer L]?
(a:F)=>Curry<(...args:L)=>R>
: R
:never;
declare function Currying<T >(fn: T): Curry<T>
# 55・Union to Intersection
type UnionToIntersection<U> = (U extends any? (a:U)=>void : never) extends (a:infer T)=>void ? T:never
# 57・Get Required
type FilterRequiredKey<T,K extends keyof T> = T extends {
[k in K]-?:T[k]
}? K :never;
type GetRequired<T> = {
[K in keyof T as FilterRequiredKey<T,K>]:T[K]
}
# 59・Get Optional
type FilterOptionalKey<T,K extends keyof T> = T extends {
[k in K]-?:T[k]
}? never:K;
type GetOptional<T> = {
[K in keyof T as FilterOptionalKey<T,K>]:T[K]
}
# 89・Required Keys
type RequiredKeys<T , K = keyof T> = K extends keyof T ?
T extends Required<Pick<T,K>> ? K : never
:never
# 90・Optional Keys
type OptionalKeys<T,K = keyof T> = K extends keyof T?
T extends Required<Pick<T,K>>?never:K
:never;
# 112・Capitalize Words
type CapitalizeWords<S extends string> = Capitalize<
CapitalizeSeparator< CapitalizeSeparator<CapitalizeSeparator<S,' '>,','> ,'.' >
>
type CapitalizeSeparator<T extends string,S extends string> = T extends `${infer F}${S}${infer L}`?
`${Capitalize<F>}${S}${Capitalize<CapitalizeSeparator<L,S>>}`:T
# 114・CamelCase
type CamelCase<S extends string,S1 = Lowercase<S>> = S1 extends `${infer F}_${infer R}`?`${F}${Capitalize<CamelCase<R>>}`:S1
# 147・C-printf Parser
type ControlsMap = {
c: 'char',
s: 'string',
d: 'dec',
o: 'oct',
h: 'hex',
f: 'float',
p: 'pointer',
}
type ParsePrintFormat<S extends string,T extends string[] = []> = S extends `${infer F}%${infer K}${infer R}`?
K extends keyof ControlsMap?
ParsePrintFormat<R,[...T,ControlsMap[K]]>
:ParsePrintFormat<R,T>
:T
# 223・IsAny
type IsAny<T> = 0 extends (1&T) ? true:false
# 300・String to Number
type Make10<T extends any[]> = [
...T,
...T,
...T,
...T,
...T,
...T,
...T,
...T,
...T,
...T,
]
type Make1<S extends string,T extends any[] = []> = `${T['length']}` extends S?T:Make1<S,[0,...T]>
type ToTuple<S extends string,T extends any[] = []> = S extends `${infer F}${infer R}`?ToTuple<R,[...Make10<T>,...Make1<F>]>:T
type ToNumber<S extends string> = ToTuple<S>['length']
A better way
type ToNumber<S extends string> = S extends `${infer T extends number}`?T:never
# 399・Tuple Filter
type FilterOut<T extends any[], F> = T extends [infer I,...infer R]?
[I] extends [F] ? FilterOut<R,F>: [I,...FilterOut<R,F>]
:[]
# 472・Tuple to Enum Object
type Tuple2Object1<T extends readonly any[]> = {
readonly [K in T[number] as Capitalize<K>]:K
}
type Copy<T> = {
[K in keyof T]:T[K]
}
type Tuple2Object2<T extends readonly any[],C extends any[] = []> = T extends readonly [infer F,...infer R]?
{
readonly [K in (F&string) as Capitalize<K> ]:C['length']
} & Tuple2Object2<R,[...C,0]>
:{}
type Enum<T extends readonly string[], N extends boolean = false> = N extends false ? Tuple2Object1<T>:Copy<Tuple2Object2<T>>
# 651・Length of String 2
type LengthOfString<S extends string,C extends number[] = []> = S extends `${infer F0}${infer F1}${infer F2}${infer F3}${infer F4}${infer F5}${infer F6}${infer F7}${infer F8}${infer F9}${infer R}`? LengthOfString<R,[...C,0,1,2,3,4,5,6,7,8,9]>
: S extends `${infer F}${infer R}`?
LengthOfString<R,[...C,0]>
:C['length']
# 847・String Join
type Join<
T extends any[],
U extends string | number,
R extends string = ''
> =
T extends [infer F,...infer L]?
L['length'] extends 0?
`${R extends ''?'':`${R}${U}`}${F&string}`
:Join<L,U,`${R extends ''?'':`${R}${U}`}${F&string}`>
:R
declare function join<U extends string>(delimiter: U): <T extends string[]>(...parts: T) => Join<T,U>;
# 956・DeepPick
type DeepPick<T extends Record<string,any>, U extends string> = (U extends string?
U extends `${infer F}.${infer R}`?
(arg:{
[K in F]:DeepPick<T[F],R>
})=>void
:U extends keyof T?
(arg:Pick<T,U>)=>void
:(arg:unknown)=>void
:never
) extends (arg:infer Z)=>void? Z:never;
# 1383・Camelize
type CamelizeWord<T extends string> = T extends `${infer F}_${infer L}`?`${F}${Capitalize<L>}`:T
type Camelize<T> = T extends any[]?
T extends [infer F,...infer R]?
[Camelize<F>,...Camelize<R>]
:[]
:
T extends Record<string,any>?
{
[K in keyof T as CamelizeWord<K&string>]:Camelize<T[K]>
}
:T
# 2095・Drop String
type DropOne<S extends string,R extends string> = S extends `${infer A}${R}${infer B}`?
DropOne<`${A}${B}`,R>
:S
type DropString<S extends string, R extends string> = R extends `${infer F}${infer L}`?
DropString<DropOne<S,F>,L>
:S
# 2822・Split
type NormalSplit<S extends string, SEP extends string> = S extends `${infer F}${SEP}${infer R}`?[
F,
...Split<R,SEP>
]:[S]
type StringToTuple<S extends string> = S extends `${infer F}${infer R}`?[F,...StringToTuple<R>]:[]
type Split<S extends string, SEP extends string> = string extends S?
string[]
:SEP extends ''?
StringToTuple<S>
:NormalSplit<S,SEP>
# 2828・ClassPublicKeys
解法一:
type ClassPublicKeys<T extends any,K = keyof T> = K extends keyof T? T extends Pick<T,K>?K:never : never;
解法二:
type ClassPublicKeys<A> = keyof A
# 2857・IsRequiredKey
type IsRequiredKey<T, K extends keyof T> = (K extends keyof T?
T extends Required<Pick<T,K>>?true:false
:never) extends true?true:false;
# 2949・ObjectFromEntries
解法1:
type Copy<T> = {
[K in keyof T]:T[K]
}
type ObjectFromEntries<T extends [string,any]> = Copy<(T extends any? (arg:{
[K in T[0]]:T[1]
})=>void:never) extends (arg:infer U)=>void ?U:never>;
解法2:
type ObjectFromEntries<T extends [string,any]> = {
[K in T as K[0]]:K[1]
}
# 4037・IsPalindrome
type StringToTuple<T extends string> = T extends `${infer F}${infer R}`? [F,...StringToTuple<R>]:[];
type IsIsPalindromeArray<T extends any[]> = T extends [infer F,...infer M,infer L] ?
F extends L?IsIsPalindromeArray<M>:false
:true;
type IsPalindrome<T extends string | number> = IsIsPalindromeArray<StringToTuple<`${T}`>>
# 5423・Intersection
type ToUnion<T> = T extends any[]? T[number]:T;
type Intersection<T extends any[],R = ToUnion<T[0]>> = T extends [infer F,...infer L]? Intersection<L,R & ToUnion<F>>:R
# 6141・Binary to Decimal
type BinaryToDecimal<
S extends string,
R extends any[] = []
> =
S extends `${infer F}${infer L}`?
F extends '0'? BinaryToDecimal<L,[...R,...R]>:BinaryToDecimal<L,[...R,...R,1]>
:R['length']
# 7258・Object Key Paths
type GenNode<K extends string | number,IsRoot extends boolean> = IsRoot extends true? `${K}`: `.${K}` | (K extends number? `[${K}]` | `.[${K}]`:never)
type ObjectKeyPaths<
T extends object,
IsRoot extends boolean = true,
K extends keyof T = keyof T
> =
K extends string | number ?
GenNode<K,IsRoot> | (T[K] extends object? `${GenNode<K,IsRoot>}${ObjectKeyPaths<T[K],false>}`:never)
:never;
# 8804・Two Sum
type MakeArr<T extends number,R extends number[] = []> = R['length'] extends T? R:MakeArr<T,[...R,0]>
type TwoSum<
T extends number[],
U extends number,
C extends number[] = []
> =
T extends [infer F,...infer R]?
[
U extends [...MakeArr<F&number>,...C]['length']? true:false,
F extends U?true:false
] extends [true,false]
?
true:
R extends number[]?
TwoSum<R,U,C | MakeArr<F&number>>
:false
:false
# 9155・ValidDate
type one2nine = '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
type zero2nine = '0' | one2nine;
type thirty = `0${one2nine}` | `1${zero2nine}` | `2${zero2nine}` | '30'
type thirtyone = thirty | '31'
type twentyeight = Exclude<thirty,'30' | '29'>
type DateMap = {
'01':thirtyone;
'02':twentyeight;
'03':thirtyone;
'04':thirty;
'05':thirtyone;
'06':thirty;
'07':thirtyone;
'08':thirtyone;
'09':thirty;
'10':thirtyone;
'11':thirty;
'12':thirtyone;
}
type ValidDate<
T extends string
> =
T extends `${infer F}${infer S}${infer D}`?
`${F}${S}` extends keyof DateMap?
D extends DateMap[`${F}${S}`]?true:false
:false
:never;
# 9160・Assign
type Merge<T> = {
[K in keyof T]:T[K]
}
type Assign<
T extends Record<string, unknown>,
U extends any[]
> =
U extends [infer F,...infer L]?
F extends Record<string,unknown>?
Assign<Omit<T,keyof F>& F,L >
:Assign<T,L>
:Merge<T>
# 9384・Maximum
type ParseNumber<
S extends string
> =
S extends `${infer I}.${infer D}`?
[I,D]
:[S,'']
// l -> -1 e->0 g->1
type CompareLength<
A extends string,
B extends string,
> =
A extends `${string}${infer AR}`?
B extends `${string}${infer BR}`?
CompareLength<AR,BR>
:1
:
B extends A?
0:-1
type GreatConfig = {
"0": '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8'| '9'
"1": '2' | '3' | '4' | '5' | '6' | '7' | '8'| '9',
'2': '3' | '4' | '5' | '6' | '7' | '8'| '9',
"3": '4' | '5' | '6' | '7' | '8'| '9',
"4": '5' | '6' | '7' | '8'| '9',
"5": '6' | '7' | '8'| '9',
'6': '7' | '8'| '9',
"7": '8'| '9'
"8": '9',
'9': never,
}
type CompareDigit<
A extends string,
B extends string,
> =
A extends B?
0:
A extends keyof GreatConfig?
B extends GreatConfig[A]?
-1:1
:never
type CompareDigits<
A extends string,
B extends string,
> =
A extends `${infer AF}${infer AR}`?
B extends `${infer BF}${infer BR}`?
CompareDigit<AF, BF> extends infer CR?
CR extends 0?
CompareDigits<AR, BR>
:CR
:never
: 1
:
B extends A?
0:-1
type CompareNonNegetive<
T extends string,
U extends string,
TP extends [string,string] = ParseNumber<T>,
UP extends [string,string] = ParseNumber<U>,
ByLength extends (0 | 1 | -1) = CompareLength<TP[0],UP[0]>
> =
ByLength extends 0?
TP[0] extends UP[0]?
CompareDigits<TP[1],UP[1]>
:CompareDigits<TP[0],UP[0]>
:ByLength
type LTE<
A extends number,
B extends number,
> =
`${A}` extends `-${infer ABS_A}`?
`${B}` extends `-${infer ABS_B}`?
CompareNonNegetive<ABS_B,ABS_A> extends 1?false:true
: true
:
`${B}` extends `-${string}`?
false:
CompareNonNegetive<`${A}`,`${B}`> extends 1? false:true
type Max<
T extends number[],
R extends number
> =
T extends [infer F extends number,...infer L extends number[]]?
LTE<R,F> extends true?
Max<L,F>: Max<L,R>
:R
type Maximum<T extends number[]> =
T['length'] extends 0?
never:
Max<T,T[0]>
# 9775・Capitalize Nest Object Keys
type CapitalizeNestObjectKeys<T> = T extends readonly any[]
? {
[K in keyof T]: CapitalizeNestObjectKeys<T[K]>;
}
: T extends Record<keyof any, any>
? {
[K in keyof T as Capitalize<K & string>]: CapitalizeNestObjectKeys<T[K]>;
}
: T;
# 13580・Replace Union
type Replace<T, U extends [any,any][]> =
U extends [
infer F extends [any,any],
...infer R extends [any,any][]
]?
T extends F[0]?
F[1]:
Replace<T,R>
:never
type UnionReplace<T, U extends [any, any][]> =
T extends any?
T extends U[number][0]?
Replace<T,U>:T
:never
# 14080・FizzBuzz
type FizzBuzz<
N extends number,
R extends string[] = [],
Three extends any[] = [0],
Five extends any[] = [0]
> =
R['length'] extends N?
R:
[Three['length'],Five['length']] extends [3,5]?
FizzBuzz<N,[...R,'FizzBuzz'],[0],[0]>:
Three['length'] extends 3?
FizzBuzz<N,[...R,'Fizz'],[0],[...Five,0]>:
Five['length'] extends 5?
FizzBuzz<N,[...R,'Buzz'],[...Three,0],[0]>:
FizzBuzz<N,[...R,`${[...R,0]['length']}`],[...Three,0],[...Five,0]>
# 14188・Run-length encoding
type Make10<S extends string> = `${S}${S}${S}${S}${S}${S}${S}${S}${S}${S}`
type Repeat<T extends string,N extends string,R extends string = ''> =
N extends `${infer F}${infer L}`?
F extends '1'?
Repeat<T,L,`${Make10<R>}${T}`>:
F extends '2'?
Repeat<T,L,`${Make10<R>}${T}${T}`>:
F extends '3'?
Repeat<T,L,`${Make10<R>}${T}${T}${T}`>:
F extends '4'?
Repeat<T,L,`${Make10<R>}${T}${T}${T}${T}`>:
F extends '5'?
Repeat<T,L,`${Make10<R>}${T}${T}${T}${T}${T}`>:
F extends '6'?
Repeat<T,L,`${Make10<R>}${T}${T}${T}${T}${T}${T}`>:
F extends '7'?
Repeat<T,L,`${Make10<R>}${T}${T}${T}${T}${T}${T}${T}`>:
F extends '8'?
Repeat<T,L,`${Make10<R>}${T}${T}${T}${T}${T}${T}${T}${T}`>:
F extends '9'?
Repeat<T,L,`${Make10<R>}${T}${T}${T}${T}${T}${T}${T}${T}${T}`>:
Repeat<T,L,Make10<R>>
:R
namespace RLE {
type Length<T extends number> = T extends 1?'':`${T}`
export type Encode<S extends string,R extends string = '',Q extends string[] = []> =
S extends `${infer F}${infer L}`?
Q['length'] extends 0?
Encode<L,R,[F]>
:F extends Q[0]?
Encode<L,R,[...Q,F]>
:Encode<L,`${R}${Length<Q['length']>}${Q[0]}`,[F]>
:Q['length'] extends 0?
R:`${R}${Length<Q['length']>}${Q[0]}`
type Num = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
export type Decode<S extends string,N extends string = '',R extends string = ''> =
S extends `${infer F}${infer L}`?
F extends Num?
Decode<L,`${N}${F}`,R>
:Decode<L,'',`${R}${Repeat<F,N extends ''?'1':N>}`>
:R
}
# 15260・Tree path array
type Path<T,S extends any[] = [],K extends keyof T = keyof T> =
K extends keyof T?
[...S,K] | (T[K] extends Record<keyof any,any>? Path<T[K],[...S,K]>:never)
:never
# 19458・SnakeCase
type SnakeCase<
T extends string,
R extends string = ''
> =
T extends `${infer F}${infer L}`?
F extends Uppercase<F>?
SnakeCase<L,`${R}_${Lowercase<F>}` >
:SnakeCase<L,`${R}${F}` >
:R;
# 25747・IsNegativeNumber
type IsUnion<T,U = T> = T extends U ?
[U] extends [T]?false:true
:never
type IsNegativeNumber<
T extends number
> =
IsUnion<T> extends true?
never:
number extends T?
never:
`${T}` extends `-${string}`?
true:false
# 28143・OptionalUndefined
type Merge<T> = {
[K in keyof T]:T[K]
}
type OptionalUndefined<
T,
Props extends keyof T = keyof T,
OptionsProps extends keyof T =
Props extends keyof T?
undefined extends T[Props]?
Props:never
:never
> =
Merge<{
[K in OptionsProps]?:T[K]
} & {
[K in Exclude<keyof T,OptionsProps> ]:T[K]
}>
# 30575・・OptionalUndefined
type MakePrefix<
S extends string,
P extends string = ''
> =
S extends `${string}${infer R}`?
MakePrefix<R,`${P}0`>
:P
type Pad<S1 extends string,S2 extends string> =
[S1,S2]extends [`${string}${infer RS1}`,`${string}${infer RS2}`]?
Pad<RS1,RS2>: [MakePrefix<S2>,MakePrefix<S1>]
type _XOR<
S1 extends string,
S2 extends string,
R extends string = ''
> =
[S1,S2] extends [`${infer F1}${infer R1}`,`${infer F2}${infer R2}`]?
_XOR<R1,R2,`${R}${F1 extends F2?'0':'1'}`>
:R
type BitwiseXOR<
S1 extends string,
S2 extends string
> =
Pad<S1,S2> extends [infer P1 extends string,infer P2 extends string]?
_XOR<`${P1}${S1}`,`${P2}${S2}`>
:never