TypeScript: 第一个 TypeScript 程序

最后更新:2026-08-26

学完安装配置,现在动手写你的第一个 TypeScript 程序——从代码到运行,完整走一遍 TS 的工作流程。

1. 创建项目文件

在上节课创建的项目目录中,新建 src/hello.ts

TEXT 📖 仅展示
my-project/
├── src/
│   └── hello.ts      ← 新建这个文件
├── tsconfig.json
└── package.json

hello.ts 中写入以下代码:

TYPESCRIPT
// 第一个 TypeScript 程序
let username: string = "Charlie";
let age: number = 18;

function greet(name: string, userAge: number): string {
  return name + " 今年 " + userAge + " 岁";
}

console.log(greet(username, age));

这段代码和 JavaScript 最大的区别在于——每个变量和参数后面多了一个 类型注解: string: number)。


2. 类型注解初体验

类型注解是 TypeScript 最核心的语法,格式很简单:变量名 + 冒号 + 类型

TYPESCRIPT
let 变量名: 类型 = 值;

(1) 常见基础类型注解

TYPESCRIPT
let name: string = "Diana";       // 字符串
let age: number = 20;            // 数字
let isStudent: boolean = true;   // 布尔值
let score: number = 95.5;        // 小数也是 number
let nothing: null = null;        // null
let empty: undefined = undefined; // undefined

(2) 函数的类型注解

函数需要标注两部分:参数类型返回值类型

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

▶ 示例:带类型注解的函数

TYPESCRIPT
// 计算两数之和
function add(a: number, b: number): number {
  return a + b;
}

// 拼接字符串
function joinWords(first: string, second: string): string {
  return first + " " + second;
}

console.log(add(3, 5));
console.log(joinWords("你好", "世界"));
▶ 试一试

输出:

TEXT 📖 仅展示
8
你好 世界
💡 提示: 如果函数没有返回值,返回值类型写 voidfunction log(msg: string): void { console.log(msg); }


3. 编译 TypeScript 代码

写好 .ts 文件后,需要编译成 .js 才能运行。

(1) 手动编译单文件

BASH
tsc src/hello.ts

这会在同目录下生成 src/hello.js。打开看看,你会发现类型注解全都消失了:

JAVASCRIPT
// 编译后的 hello.js
var username = "Charlie";
var age = 18;
function greet(name, userAge) {
    return name + " 今年 " + userAge + " 岁";
}
console.log(greet(username, age));

这就是 TypeScript 的类型擦除——类型注解只在编译时起作用,编译后的 JavaScript 代码和手写的 JS 几乎一模一样。

(2) 使用 tsconfig.json 编译整个项目

如果项目中有 tsconfig.json,直接在项目根目录执行:

BASH
tsc

编译器会按照配置文件中的 rootDiroutDir 批量编译所有 .ts 文件。

▶ 示例:编译并运行

BASH
# 进入项目目录
cd my-project

# 编译(根据 tsconfig.json 配置)
tsc

# 运行编译后的 JS
node dist/hello.js

输出:

TEXT 📖 仅展示
Charlie 今年 18 岁
📌 重点: 你运行的是 dist/hello.js,不是 src/hello.ts。TypeScript 的开发流程永远是:写 .ts → 编译 → 运行 .js


4. 体验类型检查的威力

TypeScript 的核心价值——编译时发现错误。让我们故意写错代码,看看 TypeScript 如何拦住你。

(1) 类型不匹配

TYPESCRIPT
let score: number = 90;
score = "优秀";  // ❌ 错误:不能将类型"string"分配给类型"number"

JavaScript 中这段代码"合法"运行,但后续用 score 做数学运算时就会出问题。TypeScript 直接在编译时拦住。

(2) 参数类型错误

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

add(3, "5");  // ❌ 错误:类型"string"的参数不能赋给类型"number"的参数

JavaScript 中 add(3, "5") 会返回 "35"(字符串拼接),这几乎肯定不是你想要的结果。TypeScript 提前告诉你参数传错了。

(3) 调用不存在的方法

TYPESCRIPT
let name: string = "Charlie";
name.toFixed(2);  // ❌ 错误:类型"string"上不存在属性"toFixed"

toFixednumber 类型的方法,string 上没有。JavaScript 会在运行时报 TypeError,TypeScript 编译时就拦住了。

▶ 示例:对比 JavaScript 和 TypeScript 的错误检测

TYPESCRIPT
// ===== JavaScript 版本:运行时才发现问题 =====
let userAge = "25";           // 字符串 "25"
let nextYear = userAge + 1;   // 不会报错,但结果是 "251" 而不是 26
console.log(nextYear);        // 输出 "251" —— 不是我们想要的!

// ===== TypeScript 版本:编译时就拦住 =====
let userAge2: number = 25;    // 明确标注为数字
let nextYear2: number = userAge2 + 1;  // 正确:25 + 1 = 26
console.log(nextYear2);       // 输出 26
▶ 试一试

输出:

TEXT 📖 仅展示
251
26
🔥 易错: JavaScript 中 "25" + 1 得到 "251" 而不是 26,这是初学者最容易踩的坑。TypeScript 通过类型检查,在编译时就能帮你避免这类问题。


5. tsc --watch 自动编译

每次修改 .ts 文件都手动跑 tsc 太麻烦了。--watch(简写 -w)模式让编译器监听文件变化,保存即编译:

BASH
tsc --watch

或者指定单文件:

BASH
tsc src/hello.ts --watch

开启后,终端会显示:

TEXT 📖 仅展示
[8:30:15 PM] Starting compilation in watch mode...
[8:30:15 PM] Found 0 errors. Watching for file changes.

每次保存文件,它自动重新编译,你只需要关注 node dist/xxx.js 运行结果即可。

▶ 示例:开发时的完整工作流

BASH
# 终端 1:开启自动编译
tsc --watch

# 终端 2:运行并测试
node dist/hello.js
# 修改 src/hello.ts 后再运行
node dist/hello.js
💡 提示: 也可以安装 ts-node 直接运行 .ts 文件(跳过手动编译步骤):npm install -g ts-node,然后 ts-node src/hello.ts。学习阶段这个工具非常方便,但生产环境还是要走编译流程。


6. 类型推断——TypeScript 的聪明之处

你可能注意到:并非所有变量都需要写类型注解。TypeScript 很聪明,它能根据初始值自动推断变量类型:

TYPESCRIPT
let name = "Diana";      // TS 自动推断为 string
let age = 20;           // TS 自动推断为 number
let isActive = true;    // TS 自动推断为 boolean

这和下面这段代码完全等价

TYPESCRIPT
let name: string = "Diana";
let age: number = 20;
let isActive: boolean = true;

规则很简单:有初始值时,TypeScript 能推断出类型,你可以省略类型注解;没有初始值时,必须显式标注。

▶ 示例:什么时候必须写类型注解

TYPESCRIPT
// ✅ 有初始值——类型可以推断,注解可省略
let message = "Hello";
let count = 0;

// ❌ 没有初始值——必须标注类型,否则 TS 默认为 any
let userId: number;       // 必须标注
let userEmail: string;    // 必须标注

// ❌ 不标注 = 隐式 any(strict 模式下会报错)
let userId2;              // ❌ 错误:变量隐式具有"any"类型
▶ 试一试
📌 重点:strict: true 模式下,没有初始值又不标注类型的变量会报错。这是好事——强制你明确每个变量的类型,避免模糊的 any 满天飞。


❓ 常见问题

Q 类型注解会不会让代码变长变难写?
A 会多写几个字,但省下的是调试时间。就像出门前花10秒看天气预报带把伞,比淋雨后花1小时换衣服划算得多。而且 TypeScript 有类型推断,很多地方不需要手写注解。
Q 编译后的 JS 代码为什么用 var 而不是 let?
A 这取决于 tsconfig.json 中的 target 设置。如果你把 target 设为 ES5(很旧的版本),编译器会把 let/const 转换为 var 以保证兼容性。设为 ES2020 或更高版本就会保留 let/const。推荐设为 ES2020。
Q 每次都要手动运行 node dist/xxx.js 太麻烦了,有没有更方便的方式?
A 有。安装 ts-node(npm install -g ts-node)后可以直接 ts-node src/xxx.ts,跳过手动编译步骤。VS Code 的 Code Runner 插件也支持一键运行 TS 文件。但正式项目仍然建议走 tsc 编译流程。
Q 看到类型错误但程序还能运行,可以先不管吗?
A 技术上可以——tsc 报错但仍然会生成 JS 文件(除非有严重语法错误)。但强烈建议修完所有类型错误再运行。这些错误不是"建议",而是"真的会出问题的地方"。放任不管,等于把 TypeScript 降级成了拼写检查器。

📖 小节

📝 作业

  1. 基础题(难度⭐):创建 src/hello.ts,定义三个带类型注解的变量(string、number、boolean),编译运行后用 console.log 输出它们的值。
  2. 进阶题(难度⭐⭐):写一个带类型注解的函数 calculateArea(width: number, height: number): number 计算矩形面积,故意传入一个字符串参数,观察 TypeScript 编译时的报错信息,然后修复错误。
  3. 挑战题(难度⭐⭐⭐):对比 JavaScript 和 TypeScript 对同一组错误代码的处理方式——写一段 JS 代码包含3种类型错误(字符串当数字、调用不存在的方法、undefined 属性访问),然后用 TypeScript 重写,记录 TypeScript 分别在第几行报了什么错。
Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏