StartsWith
挑战
实现 StartsWith<T, U>
,接受 2 个字符串类型并返回 T
是否以 U
开头。例如:
type a = StartsWith<"abc", "ac">; // expected to be false
type b = StartsWith<"abc", "ab">; // expected to be true
type c = StartsWith<"abc", "abcd">; // expected to be false
解答
了解 Typescript 中的模板字面量类型,解决方案就变得十分明显了。让我们从保存 any
类型的初始类型开始:
type StartsWith<T, U> = any;
我们需要检查输入类型参数 T
是否以字面量 U
开始。我会先做的简单一些,通过使用
条件类型来检查 T
是否为 U
:
type StartsWith<T, U> = T extends `${U}` ? never : never;
如果输入类型参数 T
和类型参数 U
相同,我们会进入条件类型的 true 分支。但是,
我们不需要它们相等。我们需要检查它是否以 U
开始。换句话说,我们不关心字面量
U
后面是否有其它东西。因此,在这里使用 any
类型:
type StartsWith<T, U> = T extends `${U}${any}` ? never : never;
如果类型 T
匹配以 U
开头的字符串的模式,则返回 true
类型,否则返回
false
:
type StartsWith<T, U> = T extends `${U}${any}` ? true : false;
我们通过了所有的测试用例,但是我们仍然得到了一个编译错误,说“Type ‘U’ is not
assignable to type ‘string | number | bigint | boolean | null | undefined’.”。那
是因为我们没有在泛型上添加一个约束来表明 U
是一个字符串。让我们添加它:
type StartsWith<T, U extends string> = T extends `${U}${any}` ? true : false;
评论