type Dict = {
d: number
s: string
}
type Format<T extends string> = T extends `${string}%${infer F}${infer rest}` ? F extends keyof Dict ? (arg: Dict[F]) => Format<rest> : Format<rest> : string
Solution by ouzexi #34227
type PrintTypeMap = {
s: string;
d: number;
};
type Format<T extends string> =
T extends `${string}%${infer Letter}${infer Rest}`
? Letter extends keyof PrintTypeMap
? (arg: PrintTypeMap[Letter]) => Format<Rest>
: Format<Rest>
: string;
Solution by Vampirelee #32622
type Types<
T extends string,
V extends (string | number)[] = [],
> = T extends `${string}%${infer C}${infer L}`
? Types<L, C extends "s" ? [...V, string] : C extends "d" ? [...V, number] : V>
: V;
type Func<A, F = string> = A extends [...infer H, infer L] ? Func<H, (x: L) => F> : F;
type Format<T extends string> = Func<Types<T>>;
Solution by alexandroppolus #32290
// your answers
type Format<T extends string, R = string, HasSign extends boolean = false> =
T extends `${infer F}${infer Rest}`
? HasSign extends true
? F extends 's'
? (s: string) => Format<Rest, R, false>
: F extends 'd'
? (d: number) => Format<Rest, R, false>
: Format<Rest, R, false>
: F extends '%'
? Format<Rest, R, true>
: Format<Rest, R, false>
: R
Solution by 437204933 #29571
type Controls = {
s: [s1: string],
d: [d1: number]
};
type Format<T extends string, O = string> =
T extends `${string}%${infer C}${infer Tail}`
? C extends keyof Controls
? Format<
Tail,
O extends (...args: infer Args) => infer Result
? (...args: Args) =>
(...args: Controls[C]) => Result
: (...args: Controls[C]) => O
>
: Format<Tail, O>
: O;
Solution by AntonPieper #26362
type FormatType = { s: string, d: number, f: number/*, ...*/ };
type Format<T extends string> = T extends `${any}%${infer S}${infer R}` ?
S extends keyof FormatType ? (arg: FormatType[S]) => Format<R> : Format<R> :
string;
// old way
// type Format<T extends string> = T extends `${any}%${infer F}${infer R}` ?
// (F extends `${`d` | `s`}` ?
// (fill: F extends `d` ? number : string) => Format<R> :
// Format<R>) :
// string;
Solution by E-uler #24858
// your answers
type FormatMap = {
s:string,
d:number
}
type GetNextChar<C,Last>= Last extends '%' ? '':C
type GetType<C,Last> = Last extends '%'
? C extends keyof FormatMap
? FormatMap[C]
:'none'
:'none'
type GenResult<Arr extends any[],R extends any=string>= Arr extends [infer F,...infer O] ? GenResult<O,(a:F)=>R>: R
type Format<T extends string,Last extends string='',Result extends any[] = []> = T extends `${infer L}${infer R}`
? GetType<L,Last> extends infer Type
? Type extends 'none'
? Format<R,GetNextChar<L,Last>,Result>
: Format<R,GetNextChar<L,Last>,[Type,...Result]>
: GenResult<Result>
: GenResult<Result>
Solution by walker-hzx #24737
type FormatTypes = {
s: [s1: string];
d: [d1: number];
}
type Format<T extends string> = T extends `${string}%%${infer TRest extends string}` ? Format<TRest> : (
T extends `${string}%${infer F extends keyof FormatTypes}${infer TRest extends string}` ? (
(...args: FormatTypes[F]) => Format<TRest>
) : string
)
type T = Format<'a%dbc%s'> // type T = (d1: number) => (s1: string) => string
Solution by BOCbMOU #23835
interface Dict {
s: string
d: number
}
type Format<T extends string> =
T extends `${infer _}%${infer X}${infer R}`
? X extends keyof Dict
? (x: Dict[X]) => Format<R>
: Format<R>
: string
Solution by drylint #22268
type ControlsMap = {
s: string;
d: number;
};
type Format<T extends string> = T extends `${string}%${infer C}${infer Rest extends string}` ?
C extends keyof ControlsMap ? (arg: ControlsMap[C]) => Format<Rest> : Format<Rest>
: string;
Solution by Karamuto #22001
type ControlsMap = {
s: string;
d: number;
};
type Format<T extends string> = T extends `${string}%${infer Control}${infer Rest}`
? Control extends keyof ControlsMap
? (n: ControlsMap[Control]) => Format<Rest>
: Format<Rest>
: string;
type FormatCase1 = Format<'%sabc'>; // FormatCase1 : (n: string) => string
type FormatCase2 = Format<'a%sbc'>; // FormatCase2 : (n: string) => string
type FormatCase3 = Format<'a%dbc'>; // FormatCase3 : (n: number) => string
type FormatCase4 = Format<'a%%dbc'>; // FormatCase4 : string
type FormatCase5 = Format<'a%dbc%s'>; // (n: number) => (n: string) => string>
type FormatCase6 = Format<'a%%%dbc'>; // (n: number) => string>
Solution by zqiangxu #21702
type Arguments = {
'%d': number
'%s': string
}
type Argument<T extends string> = T extends keyof Arguments ? Arguments[T] : any
type Format<T extends string> = T extends `${string | ''}%${infer Type}${infer Rest}`
? `%${Type}` extends keyof Arguments
? (a: Argument<`%${Type}`>) => Format<Rest>
: Format<Rest>
: string
Solution by milletlovemouse #21595
// your answers
type Format<T extends string> =
T extends `${ string | '' }%${ infer Type }${ infer Rest }`
? Type extends 's'
? (s1: string) => Format<Rest>
: Type extends 'd'
? (s1: number) => Format<Rest>
: Format<Rest>
: string
Solution by YqxLzx #21063
type Format<T extends string> =
T extends `${any}%${infer A}${infer Rest}`
? A extends 's'
? (a: string) => Format<Rest>
: A extends 'd'
? (a: number) => Format<Rest>
: A extends '%'
? Format<Rest>
: string
: string
Solution by zhaoyao91 #20860
// your answers
type Format<T extends string> = T extends `${string | ""}%${infer A}${infer B}`
? A extends "s"
? (s1: string) => Format<B>
: A extends "d"
? (s1: number) => Format<B>
: Format<B>
: string;
Solution by fengjinlong #20243
type Format<T extends string> =
T extends `${ string | '' }%${ infer Type }${ infer Rest }`
? Type extends 's'
? (s1: string) => Format<Rest>
: Type extends 'd'
? (s1: number) => Format<Rest>
: Format<Rest>
: string
Solution by lvjiaxuan #19522
type MapType = {
s: string;
d: number;
};
// ε€ζεͺζζ―ε₯ζ°δΈͺ`%`ζδΌδΏηζε½ζ°γεΆζ°δΈͺ`%`εθ·³θΏε€ηε©δ½ε符串
type Format<T extends string> =
T extends `${infer F}%${infer K}${infer R}`
? (K extends keyof MapType ? (arg: MapType[K]) => Format<R> : Format<R>)
: string;
Solution by CaoXueLiang #19051
type Descriptors = {
's': string,
'd': number,
}
type Format<T extends string> =
T extends `${infer S}%%${infer E}`
? Format<`${S}${E}`>
: T extends `${string}%${infer D extends keyof Descriptors}${infer E}`
? (x: Descriptors[D]) => Format<E>
: string
Solution by BulatDashiev #16904
interface FormatMap {
's': string;
'd': number;
}
type Format${infer R}${infer E}${infer Q}
? R extends '%' ? E extends 's' | 'd' ?
(args: FormatMap[E]) => Format<${Q}
> : Format<${E}${Q}
> : Format<${E}${Q}
> : string;
Solution by my5201314zwl #16499
// your answers
type O = {
'd': number
's': string
}
type Format<T extends string, F extends any = string> =
T extends `${infer J}${infer K}${infer L}` ? J extends '%' ? K extends 'd' | 's' ? Format<L, F extends (args: infer A) => infer R ? (args: A) => (args: O[K]) => R : (args: O[K]) => F>
: K extends '%' ? Format<L, F>
: Format<`${K}${L}`, F>
: Format<`${K}${L}`, F>
: F
Solution by Stan-BK #16484
// your answers
type M = {
d: number;
s: string;
}
type Format<T extends string, Prev extends string = ''> = T extends `${infer F}${infer R}`
? Prev extends '%'
? F extends '%'
? Format<R, ''>
: F extends keyof M
? (arg: M[F]) => Format<R, ''>
: Format<R, F>
: Format<R, F>
: string
Solution by humandetail #16438
// your answers
type Flags = {
s: string,
d: number
}
type FlushEscape<S extends string> = S extends `${infer Pre}%%${infer Post}` ? FlushEscape<`${Pre}${Post}`> : S
type Format<
T extends string,
E extends string = FlushEscape<T>
>
= E extends `${string}%${infer Flag extends string}${infer Post}`
? (Flag extends keyof Flags
? (argument: Flags[Flag]) => Format<Post>
: Format<Post> // Ignoring flags that not exists
)
: string;
/* _____________ Test Cases _____________ */
import type { Equal, Expect } from '@type-challenges/utils'
type cases = [
Expect<Equal<Format<'abc'>, string>>,
Expect<Equal<Format<'a%sbc'>, (s1: string) => string>>,
Expect<Equal<Format<'a%dbc'>, (d1: number) => string>>,
Expect<Equal<Format<'a%%dbc'>, string>>,
Expect<Equal<Format<'a%%%dbc'>, (d1: number) => string>>,
Expect<Equal<Format<'a%dbc%s'>, (d1: number) => (s1: string) => string>>,
// These cases works too, I think that throwing type error isn't a great choice
Expect<Equal<Format<'a%dbco%s%w'>, (d1: number) => (s1: string) => string>>,
Expect<Equal<Format<'a%dbco%w%s'>, (d1: number) => (s1: string) => string>>,
]
Solution by talkenson #16311
// your answerstype Dictionary =
{
's' :string,
'd' :number
} ;
type Trim<
S extends string > =
S extends `${infer R}%%${infer U}`
? Trim<`${R}${U}`>
: S ;
type Format<
T extends string,
S extends string = Trim<T> > =
S extends`${string}%${infer R extends keyof Dictionary}${infer U}`
? (arg: Dictionary[R])=>Format<U>
: string ;
Solution by justBadProgrammer #15862
type Format<T extends string> = buildFn<getStrMarker<T>>;
type buildFn<T, Result extends string | Function = string> = T extends [...infer Rest, infer R]
? buildFn<Rest, (s1: 's' extends R ? string : number) => Result>
: Result
type getStrMarker<T, Result extends any[] = []> = T extends `${string}%${infer U extends 's' | 'd'}${infer Rest}`
? getStrMarker<Rest, [...Result, U]>
: Result;
better solution:
type Format<T extends string> = buildFn<getStrMarker<T>>;
type Marks = {
s: string;
d: number;
}
type buildFn<T, Result extends string | Function = string> = T extends [...infer Rest, infer R extends keyof Marks]
? buildFn<Rest, (s1: Marks[R]) => Result>
: Result
type getStrMarker<T, Result extends any[] = []> = T extends `${string}%${infer U extends keyof Marks}${infer Rest}`
? getStrMarker<Rest, [...Result, U]>
: Result;
use marks type to limit match mark.
Solution by ZWkang #15278
// your answers
type PrintMap = {
s: string;
d: number;
};
type Format<T extends string> = T extends `${string}%${infer A}${infer B}`
? A extends keyof PrintMap
? (a: PrintMap[A]) => Format<B>
: Format<B>
: string;
Solution by SeptEarlyMorning #11900
type Format<T extends string> =
T extends `%s${infer Rest}` ? (
(s1: string) => Format<Rest>
) : T extends `%d${infer Rest}` ? (
(d1: number) => Format<Rest>
) : (
T extends `${string}%${infer Rest}` ? (
Format<`%${Rest}`>
) : (
string
)
)
Solution by teamchong #11427
// your answers
type Format<T extends string> = T extends `${any}%${infer F extends ('s' | 'd')}${infer E}` ?
F extends 's' ?
(s1: string) => Format<`${E}`> :
(d1: number) => Format<`${E}`> :
string;
Solution by Joyee691 #11414
type Format<T extends string> = T extends `${infer Start}%${infer F & ('s' | 'd')}${infer End}`
? F extends 's'
? (s1: string) => Format<`${Start}${End}`>
: (d1: number) => Format<`${Start}${End}`>
: string
Solution by aeroxmotion #10544
type SingleFormat<T extends string> =
T extends infer I
? I extends 's'
? string
: I extends 'd'
? number
: never
: never
type Format<T extends string> =
T extends `${infer I}%${infer J}${infer K}`
? (arg: SingleFormat<J>) => Format<`${I}${K}`>
: string
Solution by DrLee-lihr #10320
type ControlsMap = {
d: number
s: string
}
type GetType<T, K extends keyof T> = T[K]
type Format<T extends string> = T extends `${infer S}%${infer C}${infer R}` ?
C extends keyof ControlsMap ?
(any: GetType<ControlsMap,C>) => Format<R> :
Format<R> :
string
Solution by sakthikumaran22 #9613