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、endsWith | boolean | "abc".includes("b") 是 true |
indexOf、lastIndexOf | number(找不到时为 -1) | "abc".indexOf("c") 是 2 |
slice、substring | string | "hello".slice(1, 3) 是 "el" |
split | string[] | "a,b".split(",") 是 ["a", "b"] |
trim、trimStart、trimEnd | string | " x ".trim() 是 "x" |
toUpperCase、toLowerCase | string | "Ts".toUpperCase() 是 "TS" |
padStart、padEnd | string | "7".padStart(3, "0") 是 "007" |
replace、replaceAll | string | "a-b-c".replaceAll("-", "") 是 "abc" |
repeat | string | "ab".repeat(2) 是 "abab" |
at | string | undefined | "abc".at(-1) 是 "c" |
match | RegExpMatchArray | 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)。