字符串类型的一些小技巧

模板字符串类型

类似于 JavaScript 中的模板字符串允许你将值插入到字符串中一样,TypeScript 中的模板字符串类型可以用来将其他类型插入到字符串类型中。

比如说我想创建一个 PngFile 类型,它需要是以 .png 结尾的字符串:

type PngFile = `${string}.png`;

这样的话,当我们定义一个 PngFile 类型的变量时,它必须以 .png  结尾:

let myImage: PngFile = "my-image.png";

当字符串与 PngFile 类型定义的模式不匹配时,TypeScript 将显示错误:

let myImage: PngFile = "my-image.jpg";
//  ^^^^^^^
// ❗Type '"my-image.jpg"' is not assignable to type '`${string}.png`'.

这种技术有多种应用。我们可以确保字符串以特定前缀开头,例如要求路由以 / 开头:

type Route = `/${string}`;
 
const myRoute: Route = "/home";
const badRoute: Route = "home";
//    ^^^^^^^^
// ❗ Type '"home"' is not assignable to type '`/${string}`'.

我们还可以确保字符串必须包含特定的子字符串,例如要求字符串必须包含 ? 才能被视为查询字符串:

type QueryString = `${string}?${string}`;
 
const myQueryString: QueryString = "search?query=hello";
const badQueryString: QueryString = "search";
//    ^^^^^^^^^^^^^^
// ❗ Type '"search"' is not assignable to type '`${string}?${string}`'.

将模板字符串类型与联合类型组合

模板字符串类型还有一个常见的用法就是是与联合类型一起使用。通过将联合类型传递给模板字符串类型,可以生成一个代表联合类型所有可能组合的类型。

例如,假设我们有一组颜色,每种颜色的色调从 100 到 900 不等:

type ColorShade = 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900;
type Color = "red" | "blue" | "green";

如果我们想组合所有可能的颜色和色调,可以使用模板字符串类型来生成一个新类型:

type ColorPalette = `${Color}-${ColorShade}`;

现在,ColorPalette 将表示颜色和色调的所有可能组合:

let color: ColorPalette = "red-500";
 
let badColor: ColorPalette = "red";
//  ^^^^^^^^
// ❗Type '"red"' is not assignable to type '"red-100" | "red-200" | "red-300" | "red-400" | "red-500" | "red-600" | "red-700" | "red-800" | "red-900" | "blue-100" | "blue-200" | "blue-300" | "blue-400" | "blue-500" | "blue-600" | ... 11 more ... | "green-900"'.

这就是 27 种可能的组合(3 种颜色乘以 9 种色调)。

转换字符串类型

TypeScript 内置有几种用于转换字符串类型的内置实用程序类型。例如,"大写 "和 "小写 "可用于将字符串转换为大写或小写:

type UppercaseHello = Uppercase<"hello">; // type UppercaseHello is "HELLO"
type LowercaseHELLO = Lowercase<"HELLO">; // type LowercaseHELLO is "hello"

Capitalize 类型可用于将字符串的首字母大写:

type CapitalizeMatt = Capitalize<"matt">; // type CapitalizeMatt is "Matt"

Uncapitalize 类型可用于将字符串的首字母变为小写:

type UncapitalizePHD = Uncapitalize<"PHD">; // type UncapitalizePHD is "pHD"