TypeScript: 第一个 TypeScript 程序
最后更新:2026-08-26
学完安装配置,现在动手写你的第一个 TypeScript 程序——从代码到运行,完整走一遍 TS 的工作流程。
1. 创建项目文件
在上节课创建的项目目录中,新建 src/hello.ts:
my-project/
├── src/
│ └── hello.ts ← 新建这个文件
├── tsconfig.json
└── package.json
在 hello.ts 中写入以下代码:
// 第一个 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 最核心的语法,格式很简单:变量名 + 冒号 + 类型。
let 变量名: 类型 = 值;
(1) 常见基础类型注解
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) 函数的类型注解
函数需要标注两部分:参数类型和返回值类型。
function 函数名(参数: 参数类型): 返回值类型 {
// 函数体
}
- 参数类型:每个参数后面加
: 类型 - 返回值类型:参数括号后面加
: 类型
▶ 示例:带类型注解的函数
// 计算两数之和
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("你好", "世界"));
输出:
8
你好 世界
void:function log(msg: string): void { console.log(msg); }
3. 编译 TypeScript 代码
写好 .ts 文件后,需要编译成 .js 才能运行。
(1) 手动编译单文件
tsc src/hello.ts
这会在同目录下生成 src/hello.js。打开看看,你会发现类型注解全都消失了:
// 编译后的 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,直接在项目根目录执行:
tsc
编译器会按照配置文件中的 rootDir 和 outDir 批量编译所有 .ts 文件。
▶ 示例:编译并运行
# 进入项目目录
cd my-project
# 编译(根据 tsconfig.json 配置)
tsc
# 运行编译后的 JS
node dist/hello.js
输出:
Charlie 今年 18 岁
dist/hello.js,不是 src/hello.ts。TypeScript 的开发流程永远是:写 .ts → 编译 → 运行 .js。
4. 体验类型检查的威力
TypeScript 的核心价值——编译时发现错误。让我们故意写错代码,看看 TypeScript 如何拦住你。
(1) 类型不匹配
let score: number = 90;
score = "优秀"; // ❌ 错误:不能将类型"string"分配给类型"number"
JavaScript 中这段代码"合法"运行,但后续用 score 做数学运算时就会出问题。TypeScript 直接在编译时拦住。
(2) 参数类型错误
function add(a: number, b: number): number {
return a + b;
}
add(3, "5"); // ❌ 错误:类型"string"的参数不能赋给类型"number"的参数
JavaScript 中 add(3, "5") 会返回 "35"(字符串拼接),这几乎肯定不是你想要的结果。TypeScript 提前告诉你参数传错了。
(3) 调用不存在的方法
let name: string = "Charlie";
name.toFixed(2); // ❌ 错误:类型"string"上不存在属性"toFixed"
toFixed 是 number 类型的方法,string 上没有。JavaScript 会在运行时报 TypeError,TypeScript 编译时就拦住了。
▶ 示例:对比 JavaScript 和 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
输出:
251
26
"25" + 1 得到 "251" 而不是 26,这是初学者最容易踩的坑。TypeScript 通过类型检查,在编译时就能帮你避免这类问题。
5. tsc --watch 自动编译
每次修改 .ts 文件都手动跑 tsc 太麻烦了。--watch(简写 -w)模式让编译器监听文件变化,保存即编译:
tsc --watch
或者指定单文件:
tsc src/hello.ts --watch
开启后,终端会显示:
[8:30:15 PM] Starting compilation in watch mode...
[8:30:15 PM] Found 0 errors. Watching for file changes.
每次保存文件,它自动重新编译,你只需要关注 node dist/xxx.js 运行结果即可。
▶ 示例:开发时的完整工作流
# 终端 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 很聪明,它能根据初始值自动推断变量类型:
let name = "Diana"; // TS 自动推断为 string
let age = 20; // TS 自动推断为 number
let isActive = true; // TS 自动推断为 boolean
这和下面这段代码完全等价:
let name: string = "Diana";
let age: number = 20;
let isActive: boolean = true;
规则很简单:有初始值时,TypeScript 能推断出类型,你可以省略类型注解;没有初始值时,必须显式标注。
▶ 示例:什么时候必须写类型注解
// ✅ 有初始值——类型可以推断,注解可省略
let message = "Hello";
let count = 0;
// ❌ 没有初始值——必须标注类型,否则 TS 默认为 any
let userId: number; // 必须标注
let userEmail: string; // 必须标注
// ❌ 不标注 = 隐式 any(strict 模式下会报错)
let userId2; // ❌ 错误:变量隐式具有"any"类型
strict: true 模式下,没有初始值又不标注类型的变量会报错。这是好事——强制你明确每个变量的类型,避免模糊的 any 满天飞。
❓ 常见问题
npm install -g ts-node)后可以直接 ts-node src/xxx.ts,跳过手动编译步骤。VS Code 的 Code Runner 插件也支持一键运行 TS 文件。但正式项目仍然建议走 tsc 编译流程。📖 小节
- 类型注解语法:
let 变量名: 类型 = 值,函数参数和返回值也可以标注 - TypeScript 编译后执行类型擦除,生成的 JS 代码不含类型信息
- TypeScript 的核心价值:编译时发现类型错误,避免运行时出问题
tsc --watch自动编译,ts-node直接运行 TS 文件- 类型推断让有初始值的变量无需手写注解,但无初始值必须标注
- 严格模式下隐式 any 会报错,这是好事——强制你写清楚类型
📝 作业
- 基础题(难度⭐):创建
src/hello.ts,定义三个带类型注解的变量(string、number、boolean),编译运行后用console.log输出它们的值。 - 进阶题(难度⭐⭐):写一个带类型注解的函数
calculateArea(width: number, height: number): number计算矩形面积,故意传入一个字符串参数,观察 TypeScript 编译时的报错信息,然后修复错误。 - 挑战题(难度⭐⭐⭐):对比 JavaScript 和 TypeScript 对同一组错误代码的处理方式——写一段 JS 代码包含3种类型错误(字符串当数字、调用不存在的方法、undefined 属性访问),然后用 TypeScript 重写,记录 TypeScript 分别在第几行报了什么错。