Trim Right
挑战
实现 TrimRight<T>
,它接收一个明确的字符串类型,并返回一个删除了尾部所有空格的
新字符串类型。例如:
type Trimmed = TrimRight<" Hello World ">; // expected to be ' Hello World'
解答
这个挑战其实和另外的 Trim 以及 Trim Left 挑战很相似。但是这个挑战我们需要做的是移除尾部 的空格。
我们仍然以一个空白类型开始:
type TrimRight<S extends string> = any;
如何检查字符串是否是以空格结束呢?我们可以通过一个输入字符串是否继承自尾部为空格 的模板字符串的条件语句来判断,模板字符串中末尾是一个空格:
type TrimRight<S extends string> = S extends `${infer T} ` ? never : never;
注意这里的类型推断 infer T
。如果字符串是以空格结尾的,我们需要获取没有空格的部
分。因此我们将除末尾空格之外的部分推断为类型 T
:
获取到尾部不包含空格的部分,我们就可以返回它:
type TrimRight<S extends string> = S extends `${infer T} ` ? T : never;
但是上面的方案只能处理结尾包含一个空格的情况,如果有多个空格该如何处理呢?要覆盖 这种情况,我们需要不断去除尾部空格直至尾部没有空格,通过递归调用本身可以轻松实 现:
type TrimRight<S extends string> = S extends `${infer T} `
? TrimRight<T>
: never;
现在,我们的类型将递归逐个删除尾部空格,直至尾部没有空格。然后进入 false
分
支。此步骤中意味着尾部没有空格,我们可以不作处理直接返回输入的字符串:
type TrimRight<S extends string> = S extends `${infer T} ` ? TrimRight<T> : S;
我想这就是解答方案。但我们通过测试用例的错误提示看到还有一些缺陷。我们没有处理制
表符和换行符。我们新增一个叫做 Whitespace
的单独类型,列出所有要处理的字符:
type Whitespace = " " | "\n" | "\t";
然后使用该类型替换我们工具类型内的空格字符串:
type TrimRight<S extends string> = S extends `${infer T}${Whitespace}`
? TrimRight<T>
: S;
最终解答如下所示:
type Whitespace = " " | "\n" | "\t";
type TrimRight<S extends string> = S extends `${infer T}${Whitespace}`
? TrimRight<T>
: S;
评论