TypeScript 编译器能直接理解什么,与框架自己定义的文件格式之间存在边界。


Vue 单文件组件的语言边界

Vue 的单文件组件(SFC)不是标准 TypeScript:

<template>
  <div>{{ count }}</div>
</template>

<script setup lang="ts">
const count = ref(0)
</script>

一个 .vue 文件包含多个语言区域:

  • <template>:模板语法,不是 JavaScript
  • <script>:TypeScript / JavaScript
  • <style>:CSS / SCSS / Less

TypeScript 编译器只理解 <script> 部分。<template> 里的 {{ count }}v-ifv-for 不是标准 JavaScript,TypeScript 无法直接解析。


vue-tsc / Volar 的作用

Vue 生态需要 vue-tsc / Volar 来桥接这个边界:

.vue 文件

vue-tsc / Volar 解析

提取 <script> → 交给 TypeScript
提取 <template> → 转换成 TypeScript 能理解的形式

类型检查

映射回模板

vue-tsc 是 Vue 的 TypeScript 编译器,它理解 .vue 文件格式,内部调用 TypeScript 来做类型检查。

Volar 是 VS Code 的 Vue 语言插件,它实现了 Vue 的语言服务,内部也使用 TypeScript。


Angular 的情况

Angular 有自己的模板语法和编译器:

@Component({
  template: `
    <div *ngIf="show">{{ message }}</div>
    <button (click)="handleClick()">Click</button>
  `
})
export class AppComponent {
  show = true
  message = 'Hello'
  handleClick() { ... }
}

Angular 的 @angular/compiler-cli 需要:

  • 解析 Angular 模板语法
  • 类型检查模板中的表达式
  • 生成类型安全的代码

这需要额外的工具链来适配 TypeScript。


设计选择,不是优劣问题

React 选择让 JSX 成为 TypeScript 的原生语法扩展,获得了开箱即用的 TypeScript 体验。

Vue 选择让 SFC 包含模板、脚本、样式三个区域,获得了更好的关注点分离,但需要额外的工具链来处理类型检查。

Angular 选择让模板有自己的一套语法,获得了更强的模板能力,但同样需要额外的工具链。

这不是"谁更好谁更差",而是不同的设计选择:

  • React:模板就是 JavaScript 表达式,TypeScript 直接理解
  • Vue:模板是独立的语言,需要工具桥接到 TypeScript
  • Angular:模板有自己的语法,需要编译器处理类型

TypeScript 编译器能理解什么,取决于框架选择让模板和 JavaScript 的关系有多近。