# 545-printf
# 题目描述
Implement Format<T extends string>
generic.
For example,
type FormatCase1 = Format<'%sabc'>; // FormatCase1 : string => string
type FormatCase2 = Format<'%s%dabc'>; // FormatCase2 : string => number => string
type FormatCase3 = Format<'sdabc'>; // FormatCase3 : string
type FormatCase4 = Format<'sd%abc'>; // FormatCase4 : string
# 分析
题目的描述不是特别清晰,可以再根据用例看下预期:
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>>,
];
可以看出来,本质是去匹配字符中 %d, %s 出现的地方,根据顺序依次作为函数入参,每次取一个(有点柯里化的意思),返回值始终是 string。
题目本身其实不复杂,只是步骤相对多一些,但是这些步骤其实都接触过,比如 147-cPrintfParser 和 柯里化。
本题,便是该两题思路的集合。直接上题解。
# 题解
// 转换字符为元组
// '%s%d' -> [string, number]
type FormatParams<T extends string> =
// 匹配 %
T extends `${any}%${infer M}${infer R}`
? M extends 'd'
? [number, ...FormatParams<R>]
: M extends 's'
? [string, ...FormatParams<R>]
: FormatParams<R>
: [];
// 转换元组为柯里化后的函数
// [string, number] -> (string) => (number) => string;
type FormatFn<T extends any[]> = T extends [infer F, ...infer R]
? (p: F) => FormatFn<R>
: // 没有元素直接返回 string
string;
type Format<T extends string> = FormatFn<FormatParams<T>>;
# 知识点
- 玩转字符匹配 infer
- 递归处理嵌套问题