外观
TypeScript 在面试里要讲清什么?
TypeScript 是带静态类型的 JavaScript。类型在编译后被擦除,不会在运行时替你校验接口返回。重点是结构类型、收窄、泛型,以及 type 和 interface 怎么选。
原理
TypeScript 使用结构类型:两个类型只要形状兼容就可以赋值,不要求同一个名字。
unknown 是安全的顶层类型,用之前必须收窄。any 会关掉这一支上的检查,把错误往后传。外部数据(JSON.parse、接口响应)先标成 unknown,再用类型守卫收窄。
ts
function lengthOf(value: string | string[]) {
if (Array.isArray(value)) return value.length
return value.length
}可辨识联合用一个共同的字面量字段区分分支。switch (action.type) 之后,每个分支里的其他字段会被收窄。
泛型把类型当成参数。function first<T>(list: T[]): T | undefined 让返回值跟着调用方的数组走,而不是退回 any。
interface 适合描述对象,并且可以多次声明合并。type 可以写联合、交叉、条件类型和映射类型。对象形状两者都能描述;需要联合时用 type。
常用工具类型:Partial、Required、Pick、Omit、Record、ReturnType。它们是映射类型,不是运行时函数。
as 是断言,告诉编译器「按这个类型看待」,不是转换。断言错了,运行时照样错。真正的转换要写检查或构造新值。
字符串联合通常比数字枚举更合适:它擦除后就是字符串,没有额外的运行时对象。enum 会生成真实代码。
打开 strict,尤其是 strictNullChecks。可空值必须在使用前排除,这是类型系统最有用的一部分。
追问
类型能代替校验吗?
不能。编译产物里没有类型。接口数据和用户输入要在运行时校验,例如用 schema 解析一遍,再得到可信的类型。
interface 声明合并什么时候是坑?
同名 interface 会悄悄合并。库的类型可以利用这一点做扩展;业务代码里同名合并常常是意外,看起来像类型变宽了。
易错点
- 把
as User当成运行时转换。它只影响编译。 any会传染。一个any参与运算,结果往往也是any。- 可选属性和
undefined在开了严格空检查时仍然要分清:属性可以不存在,和属性存在但值是undefined,在精确类型里不是同一件事。