Skip to content
第 93 / 250 章前端⏱ 10 分钟阅读

第 93 章:第一个 TypeScript 程序

学习目标

  • 编写第一个 TypeScript 函数
  • 理解类型注解的基本语法
  • 掌握从 JS 到 TS 的迁移方式
  • 理解类型推断与类型注解的区别

一、Hello World 三种写法

1.1 JavaScript 写法(基线)

javascript
// hello.js
function greet(name) {
  return 'Hello, ' + name + '!';
}

console.log(greet('Tom'));

问题name 可以传任何值(数字、对象、null),IDE 不报错。

1.2 TypeScript 写法(1.0 - 显式类型)

typescript
// hello.ts
function greet(name: string): string {  // ① 参数类型 string ② 返回类型 string
  return 'Hello, ' + name + '!';
}

console.log(greet('Tom'));
// console.log(greet(123));  // ❌ Argument of type 'number' is not assignable to parameter of type 'string'

类型注解三要素

typescript
function 函数名(参数: 参数类型): 返回类型 {
  // 函数体
}

1.3 TypeScript 写法(2.0 - 箭头函数)

typescript
// hello.ts
const greet = (name: string): string => `Hello, ${name}!`;

console.log(greet('Tom'));

1.4 TypeScript 写法(3.0 - 类型推断)

typescript
// 编译器能自动推断 string,可以省略
const greet = (name: string) => `Hello, ${name}!`;  // 推断返回 string

最佳实践:参数必须显式标注,返回类型能推断就省略。

二、变量类型注解

2.1 基本语法

typescript
// 变量名: 类型 = 值
let username: string = 'Tom';
let age: number = 18;
let isActive: boolean = true;
let skills: string[] = ['Java', 'TypeScript', 'Vue'];

2.2 常量也支持类型

typescript
const PI: number = 3.14159;
const APP_NAME: string = 'TaskFlow';

2.3 类型推断 vs 显式注解

typescript
// ✅ 推荐:能推断就省略
let count = 10;          // 推断为 number
let name = 'Tom';        // 推断为 string
let items = [1, 2, 3];   // 推断为 number[]

// ✅ 必要:参数、对象字面量、复杂类型
function add(a: number, b: number) { ... }  // 参数必须标

// ❌ 反例:画蛇添足
let count: number = 10;  // 重复,编译器已经能推断

三、第一个完整示例

3.1 完整代码

typescript
// src/user.ts
interface User {
  name: string;
  age: number;
  email: string;
}

function createUser(name: string, age: number, email: string): User {
  return { name, age, email };
}

function describeUser(user: User): string {
  return `${user.name} (${user.age}岁) 的邮箱是 ${user.email}`;
}

// 使用
const u = createUser('Tom', 18, 'tom@example.com');
console.log(describeUser(u));
// Tom (18岁) 的邮箱是 tom@example.com

3.2 编译运行

bash
pnpm tsc
node dist/user.js

四、逐步从 JS 迁移到 TS

实际项目很少"从零开始"用 TS,都是逐步迁移

4.1 第一步:先改后缀

bash
# 把 .js 改成 .ts
mv user.js user.ts

第一次改完,TS 可能会报一堆错误,先不必慌。

4.2 第二步:加 // @ts-check 注释

javascript
// user.js
// @ts-check    ← 加上这一行,VS Code 就会做类型检查

function greet(name) {
  return 'Hello, ' + name;
}

好处:不用改文件后缀,先在 JS 文件里打开检查。

4.3 第三步:允许 JS 和 TS 混编

json
// tsconfig.json
{
  "compilerOptions": {
    "allowJs": true,         // 允许编译 .js 文件
    "checkJs": false,        // 暂不检查 .js(第一阶段)
    "outDir": "./dist"
  },
  "include": ["src/**/*"]
}

这样 JS 和 TS 可以共存,逐步把 .js 改成 .ts

4.4 第四步:迁移顺序

原则:从底层向顶层迁移(叶子 → 根),避免依赖混乱。

五、常见编译错误

5.1 类型不匹配

typescript
function print(message: string): void {
  console.log(message);
}

print(123);  // ❌ TS2345: Argument of type 'number' is not assignable to parameter of type 'string'

修复

typescript
print(String(123));  // ✅ 显式转换
print(`${123}`);      // ✅ 模板字符串

5.2 缺少返回类型

typescript
function add(a: number, b: number) {
  return a + b;  // 有的项目会要求显式返回类型
}

修复

typescript
function add(a: number, b: number): number {
  return a + b;
}

5.3 隐式 any

typescript
// 严格模式下报错
function process(data) {  // ❌ Parameter 'data' implicitly has an 'any' type
  return data;
}

修复

typescript
function process(data: unknown): unknown {  // ✅ 显式标注
  return data;
}

六、tsc 命令详解

bash
# 编译指定文件
tsc hello.ts

# 编译整个项目(依赖 tsconfig.json)
tsc

# 只做类型检查,不输出文件
tsc --noEmit

# 监听模式
tsc --watch

# 编译时打印详细错误
tsc --pretty

# 指定配置文件
tsc --project tsconfig.build.json

# 增量编译(加快速度)
tsc --incremental

七、调试技巧

7.1 开启 sourceMap

json
// tsconfig.json
{
  "compilerOptions": {
    "sourceMap": true
  }
}

配合 node --enable-source-maps dist/index.js,调试时能直接跳到 .ts 源码。

7.2 使用 VS Code 调试

.vscode/launch.json

json
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "调试 TS",
      "program": "${workspaceFolder}/src/index.ts",
      "preLaunchTask": "tsc: build",
      "outFiles": ["${workspaceFolder}/dist/**/*.js"]
    }
  ]
}

F5 启动。

八、本章小结

要点关键
类型注解语法变量: 类型 = 值 / 函数(参数: 类型): 返回类型
类型推断能推断就省略返回类型
渐进式迁移@ts-checkallowJs → 逐步改后缀
编译命令tsc / tsc --watch / tsc --noEmit
严格模式开启 strict: true 后所有隐式 any 都会报错

动手练习

  1. 基础练习:写一个 calculateCircleArea(r: number): number 函数,参数是半径,返回面积
  2. 迁移练习:把之前的 JavaScript 工具函数加上类型注解
  3. 类型推断实验:故意写一个能推断的和一个不能推断的代码,对比有没有 : type 的差异

推荐阅读


下一章第 94 章:基本类型

本站基于 VitePress 构建 · 由 Codebook 团队维护