Menu

TypeScript 字符串:插值、多行字符串与包含判断

在 TypeScript 中处理字符串:用模板字面量做插值、多行字符串、判断字符串是否包含子串、常用方法及其返回类型,以及字符串字面量类型。

本页包含可运行的编辑器。编辑、运行,立即查看输出。

TypeScript 字符串就是类型为 string 的 JavaScript 字符串。要做插值,就写模板字面量:用反引号包裹,并用 ${expression} 作为占位符。单引号和双引号创建的是不支持插值的普通字符串。

三种引号写法得到的类型都是 string。$${...} 中的第一个 $ 是普通的美元符号;只有 ${ 才表示占位符的开始。

字符串插值

${ } 里可以放变量、算术运算、函数调用、三元表达式,或者嵌套的模板字面量。值转换成字符串的方式与 String(value) 相同(symbol 是例外:对它做插值会导致编译错误 TS2731,在运行时也会抛出 TypeError;请写成 String(sym))。

对对象做插值会打印 [object Object],这几乎从来都不是你想要的。请挑出需要的字段,或者使用 JSON.stringify(obj)。

多行字符串

模板字面量可以跨越多行。换行符会被保留,每行开头的缩进也会被保留,因为反引号之间的所有内容都是字符串的一部分。

当代码的缩进会混进字符串时,可以用数组加 join("\n") 来构建字符串,或者让模板字面量的各行紧贴行首。

判断字符串是否包含子串

includes 以 boolean 回答“是否包含”。startsWith 和 endsWith 检查开头和结尾。indexOf 给出位置,找不到子串时返回 -1。它们都区分大小写。

includes 还接受一个起始位置:file.includes("R", 1) 只从索引 1 开始查找。

常用方法及其类型

TypeScript 知道每个内置方法的返回类型。需要留意的是那些可能返回空值的方法,因为在 strict 模式下,使用结果之前必须先处理 null 或 undefined。

方法返回值示例
includes、startsWith、endsWithboolean"abc".includes("b") 是 true
indexOf、lastIndexOfnumber(找不到时为 -1)"abc".indexOf("c") 是 2
slice、substringstring"hello".slice(1, 3) 是 "el"
splitstring[]"a,b".split(",") 是 ["a", "b"]
trim、trimStart、trimEndstring" x ".trim() 是 "x"
toUpperCase、toLowerCasestring"Ts".toUpperCase() 是 "TS"
padStart、padEndstring"7".padStart(3, "0") 是 "007"
replace、replaceAllstring"a-b-c".replaceAll("-", "") 是 "abc"
repeatstring"ab".repeat(2) 是 "abab"
atstring | undefined"abc".at(-1) 是 "c"
matchRegExpMatchArray | null"a1".match(/\d/)
length(属性)number"abc".length 是 3

普通的索引访问 s[5] 的类型是 string,即使索引超出了末尾(此时运行时的值是 undefined)。编译选项 noUncheckedIndexedAccess 会把它变成 string | undefined。

字符串是不可变的

你无法就地修改字符串中的字符。TypeScript 会把对索引的赋值报告为错误 TS2542:Index signature in type 'String' only permits reading.;而在它编译生成的严格模式 JavaScript 中,同样的赋值会在运行时抛出 TypeError。每个看起来在修改字符串的方法,其实都返回一个新字符串。

要把其他值转换成字符串,或者把字符串转换成数字,请看 字符串转数字。

字符串字面量类型

string 接受任意文本。字符串字面量类型只接受一个确切的值,多个字面量组成的联合类型就构成了一组类似枚举的允许值:

字面量类型只在编译时检查;在运行时,label("deleted") 照样会运行并打印 Post is deleted,这里的第二行正是这样。模板字面量语法也可以用在类型层面,比如 type EventName = `on${string}`,它接受任何以 on 开头的字符串。

常见问题

TypeScript 中如何进行字符串插值?

使用模板字面量:用反引号包裹,并用 ${expression} 作为占位符,例如 `Hello, ${name}!`。花括号里可以放任何表达式,结果的类型是 string。单引号和双引号不支持插值。

TypeScript 中如何写多行字符串?

把文本放进反引号里,并在源代码中直接换行:模板字面量会保留换行符,也会保留每行开头的缩进。也可以用 .join("\n") 把由各行组成的数组拼接起来,或者在普通字符串中使用 \n。

TypeScript 中如何判断字符串是否包含某个子串?

调用 text.includes("part"),它返回一个 boolean。它区分大小写,所以要忽略大小写时,先把两个字符串都转成小写再比较:text.toLowerCase().includes(part.toLowerCase())。startsWith 和 endsWith 检查开头和结尾,indexOf 返回位置,找不到时返回 -1。

TypeScript 和 JavaScript 中的字符串有区别吗?

没有,在运行时它们就是同样的 JavaScript 字符串,方法也一样。TypeScript 增加了 string 类型,检查你调用的方法是否存在,并且知道各方法的返回类型,比如 match 可能返回 null,at 可能返回 undefined。

可以修改 TypeScript 字符串中的某个字符吗?

不可以。字符串是不可变的,s[0] = "H" 会导致编译错误 TS2542(Index signature in type 'String' only permits reading)。应该构建一个新字符串:"H" + s.slice(1)。

Coddy 编程语言插图

和 Coddy 一起学编程

开始