TypeScript 基础 / 第 7 课
类型检查到哪里为止
了解 TypeScript 编译如何检查代码、类型擦除意味着什么,以及运行时验证为何仍有必要。
浏览器执行的是 JavaScript。写 TypeScript 时,需要先经过编译:工具读取代码和类型,检查许多可静态判断的问题,再生成 JavaScript。生成结果保留可执行的语句,不保留大多数类型标注。这个过程常称为类型擦除。
例如:
function greet(name: string): string {
return `你好,${name}`;
}
const message: string = greet('小林');
编译后的 JavaScript 中,: string 不再出现,函数仍会把传入的值放进文字里。类型让编写和维护代码时更容易发现错误,但它不是 JavaScript 的运行时规则。编译器不会因为类型标注而替程序把输入转成字符串,也不会在每次函数调用时额外检查它。
异步函数也可以说明结果类型:
async function readGreeting(): Promise<string> {
return '早上好';
}
readGreeting().then((text) => console.log(text));
Promise<string> 表示这个 Promise 成功完成时会得到字符串。async 函数会返回 Promise;调用方可以用 await 或 .then() 读取完成值。这个类型帮助编译器检查函数实现和调用方式,运行时真正工作的仍是 JavaScript 的 Promise 对象。若要处理可能失败的情况,还需要单独理解拒绝状态;Promise<string> 并不会保证操作一定成功。
静态检查也不是万能证明。比如数据来自用户输入或文件,TypeScript 通常无法仅靠类型声明确认实际内容。可以把一段文字直接断言成某个对象类型,但断言只是在告诉编译器“按这个类型看待”,不会验证里面的字段。若运行时数据不符合预期,读取属性或调用方法仍可能出错。需要时应在运行时检查值,再决定如何使用它。
可以把类型理解成开发阶段的约定,而不是附着在每个 JavaScript 值上的标签。编译成功说明检查器没有发现它能识别的类型问题,不等于程序绝无错误,也不等于外部数据已验证。
小练习:const age: number = 18 编译后,变量上还带着 number 标签吗?把任意文字断言为 { name: string } 会检查文字内容吗?
答案:不会,: number 会在生成 JavaScript 时擦除。断言不会检查文字内容;要确认运行时数据有效,必须实际读取并检查它的结构和值。
互动练习:理解编译边界
TypeScript 编译成 JavaScript 后,哪项通常会被移除?
编译阶段能发现静态类型不匹配,但类型会从生成的 JavaScript 中擦除,不能代替运行时检查。