TypeScript 快速入门
引言
TypeScript(简称 TS)是由微软开发的开源编程语言,它是 JavaScript 的超集,为 JavaScript 添加了静态类型系统和其他高级特性。本文讲解了TypeScript 的核心概念和常用语法。
1 类型系统基础
TypeScript 的核心优势在于其强大的类型系统,它能在编码阶段就发现潜在的类型错误,避免运行时异常。
1.1类型约束
TypeScript 提供了三种类型约束方式,让开发者可以灵活控制变量的类型:
(1)类型推断:TypeScript 自动推断变量类型
let str1 = "abc"; // 推断为 string 类型
str1 = 10; // 报错:不能将类型 'number' 分配给类型 'string'
(2)类型注解:显式声明变量类型
let str2: string = "abc"; // 显式声明为 string 类型
str2 = 10; // 同样报错,类型系统严格检查
(3)类型断言:告诉编译器变量的实际类型
在 TypeScript 中,as number 是类型断言(Type Assertion)的语法,用于告诉编译器某个变量的实际类型,解决类型系统无法自动推断的场景。
let numArr = [1, 2, 3];
const result = numArr.find(item => item > 2) as number;
result * 5; // 正确,断言为 number 类型
【代码解释】
①Array.find() 的返回类型
TypeScript 中,Array.find(callback) 方法的返回类型是 T | undefined,其中 T 是数组元素类型。对于 number[] 数组,find() 的返回类型是 number | undefined。
②类型推断的局限性
当执行 numArr.find(item => item > 2) 时,符合条件的元素是 3,但 TypeScript 无法在编译阶段确定 find() 一定能找到元素(可能数组为空或无匹配项)。因此,result 的类型被推断为 number | undefined,而非确定的 number。
③类型断言 as number
告诉编译器 “我确定这个值是 number 类型”。断言后,编译器会忽略 undefined 可能性,允许对 result 执行 number 类型的操作(如 result * 5)。
类型断言的本质是“开发者对编译器的声明”,当你确定某个变量的实际类型时可以使用,但需注意过度使用可能掩盖真实类型错误。
1.2 基础类型与联合类型
TypeScript 支持所有 JavaScript 的基础类型,并在此基础上增加了更严格的类型定义:
①基础类型
let v1: string = "abc"; // 字符串类型
let v2: number = 10; // 数值类型
let v3: boolean = true; // 布尔类型
let nu: null = null; // null 类型
let un: undefined = undefined;// undefined 类型
【null与undefined的区别】
| 特性 | null | undefined |
|---|---|---|
| 本质 | 表示“有意为空”或“值被主动设为无” | 表示“未定义”或“值未被初始化” |
| 类型 | typeof null === "object" |
typeof undefined === "undefined" |
| 默认值 | 需主动赋值(如 let a = null) |
自动生成(变量声明未赋值、属性不存在等) |
| 语义 | 此处应该有值,但目前人为设为空 | 此处尚未有值,或值不存在 |
②联合类型:变量可以是多种类型中的一种
let v4: string | null = null; // v4 只能是 string 或 null
v4 = "hello"; // 正确
v4 = 10; // 报错:不能将 number 分配给 string | null
③字面量类型:变量只能是特定的字面量值
let v5: 1 | 2 | 3 = 2; // v5 只能是 1、2 或 3
v5 = 4; // 报错:不能将 4 分配给 1 | 2 | 3
联合类型和字面量类型结合使用,可以实现更精准的类型约束,例如定义状态码、枚举值等场景。
2 复杂数据类型
2.1 数组类型
TypeScript 为数组提供了两种类型声明方式,确保数组元素类型的一致性:
// 方式一:类型后缀语法
let arr1: number[] = [1, 2, 3]; // 数组元素必须为 number
// 方式二:泛型语法
let arr2: Array<string> = ["a", "b", "c"]; // 数组元素必须为 string
// 错误示例
arr1.push("abc"); // 报错:不能将 string 推入 number[] 数组
arr2.push(10); // 报错:不能将 number 推入 string[] 数组
2.2 元组
元组(Tuple)是 TypeScript 特有的类型,它允许定义数组的元素个数和每个位置的类型:
// 定义元组:[number, string, number?]
// 含义:第一个元素是 number,第二个是 string,第三个可选(?)且为 number
let t1: [number, string, number?] = [1, "a", 2]; // 正确
let t2: [number, string] = [1, "a"]; // 正确,可选参数可省略
let t3: [number, string] = [1]; // 报错:缺少第二个元素
let t4: [number, string] = [1, "a", 2]; // 报错:元素数量超出
元组常用于需要固定结构数据的场景,例如函数返回多个不同类型的值。
3 枚举
枚举(Enum)是 TypeScript 对 JavaScript 的重要扩展,用于定义一组具名常量:
// 定义枚举
enum MyEnum {
A,
B,
C
}
// 访问枚举值
console.log(MyEnum.A); // 输出:0(默认从 0 开始编号)
console.log(MyEnum[0]); // 输出:"A"(通过值反向查找名称)
// 带初始值的枚举
enum Color {
Red = 1,
Green = 2,
Blue = 3
}
console.log(Color.Red); // 输出:1
枚举在需要定义一组相关常量时非常有用,例如状态码、方向键、颜色等。
4 函数类型
TypeScript 为函数提供了完整的类型定义,包括参数类型和返回值类型:
// 基础函数类型定义
function add(a: number, b: number): number {
return a + b;
}
// 带默认值和可选参数的函数
function processData(
isDebug: boolean,
timeout = 1000, // 带默认值的可选参数
message?: string, // 可选参数(无默认值)
...restParams: any[] // 剩余参数(rest 参数)
): boolean {
console.log(message || "默认消息");
return isDebug;
}
// 函数调用
const result = processData(true, 2000, "自定义消息", 1, 2, 3);
console.log(result); // 输出:true
// 参数顺序规则:必选参数在前,可选参数在后
function errorExample(required: number, optional?: string) { }
errorExample("abc", 10); // 报错:参数类型不匹配且顺序错误
函数类型定义让开发者可以提前发现参数传递和返回值的类型错误,提高代码可靠性。
5 类型抽象
5.1 接口
接口(Interface)是 TypeScript 中定义对象结构的重要方式,它如同一份“契约”,规定了对象必须包含的属性和方法:
// 定义接口
interface Person {
name: string; // 必选属性
age: number; // 必选属性
address?: string; // 可选属性(?)
sayHello(): void; // 方法定义
}
// 使用接口定义对象
const user: Person = {
name: "小明",
age: 18,
sayHello() {
console.log(`你好,我是 ${this.name}`);
}
};
user.sayHello(); // 输出:你好,我是 小明
// 接口继承
interface Student extends Person {
studentId: string;
study(): void;
}
【void与undefined的区别】
| 特性 | void | undefined |
|---|---|---|
| 本质 | 函数无返回值的类型标记 | 表示“未定义”或“值未初始化” |
| 类型定义 | 专门用于函数返回值类型 | JavaScript 基础数据类型 |
| 常见场景 | 纯副作用函数(如日志、UI更新),明确告诉编译器和开发者 “此函数不返回有效数据” | 变量未赋值、对象属性不存在等 |
| 返回值含义 | 函数设计上不返回任何值 | 函数隐式返回或值自然缺失 |
| 变量赋值 | let v: void = undefined; |
let u: undefined = undefined; |
| 与其他类型兼容性 | 可赋值为undefined(严格模式下不可为null) |
可赋值给任意类型(TypeScript中需开启strict) |
| 示例函数 | function log(): void { console.log(); } |
function noReturn() { return; }(返回值类型为undefined) |
接口支持继承,可以复用已有接口的定义,适合大型项目的类型设计。
5.2 类型别名
类型别名(Type Alias)用于为复杂类型创建自定义名称,提高代码可读性:
// 为联合类型创建别名
type StrOrNum = string | number;
let a: StrOrNum = 10;
let b: StrOrNum = "abc";
// 为对象类型创建别名
type UserInfo = {
id: number;
name: string;
age?: number;
};
// 为函数类型创建别名
// 定义了一个名为 Callback 的函数类型,它接受一个参数 data(类型为 any),并且不返回任何值(void)
// any允许变量存储任意类型的值,且绕过编译器的类型检查,无法确定或不想指定变量类型时使用
type Callback = (data: any) => void;
function fetchData(url: string, callback: Callback) {
// 模拟数据请求
callback({ status: "success" });
}
类型别名可以用于任何类型,包括基本类型、联合类型、对象类型和函数类型,是提高代码可维护性的重要工具。
6 泛型
在 TypeScript 中,泛型(Generics) 是一种允许你在定义函数、类或接口时使用类型变量的特性。这些类型变量在使用时会被具体的类型所替代,从而实现代码的复用性和类型安全性。
// 泛型函数:支持任意类型的数组处理
function processArray<T>(item: T, array: T[]): T[] {
return [item, ...array];
}
// 使用泛型函数
const numArray = processArray<number>(10, [1, 2, 3]); // 类型参数显式声明
const strArray = processArray("a", ["b", "c"]); // 类型推断自动识别
// 泛型接口
interface KeyValuePair<K, V> {
key: K;
value: V;
}
// 使用泛型接口
const pair1: KeyValuePair<number, string> = { key: 1, value: "one" };
const pair2: KeyValuePair<string, boolean> = { key: "flag", value: true };
// 泛型类
class Queue<T> {
private items: T[] = [];
enqueue(item: T): void {
this.items.push(item);
}
dequeue(): T | undefined {
return this.items.shift();
}
}
// 使用泛型类
const numberQueue = new Queue<number>();
numberQueue.enqueue(10);
numberQueue.enqueue(20);
console.log(numberQueue.dequeue()); // 输出:10
泛型的核心价值在于“类型抽象”,它让你可以编写复用性高且类型安全的代码,避免为不同类型重复实现相同逻辑。
总结
- 类型系统:类型推断、类型注解和类型断言构成了 TypeScript 类型检查的基础。
- 数据类型:从基础类型到联合类型,从数组到元组,提供了丰富的类型表达能力。
- 高级特性:枚举、函数类型、接口和类型别名帮助你构建复杂的类型结构。
- 泛型编程:通过类型参数实现通用逻辑,保持类型安全的同时提高代码复用性。
TypeScript 的优势不仅在于编译时的类型检查,还在于它为大型项目提供了更好的代码组织方式和可维护性。随着项目规模的扩大,TypeScript 的类型系统能显著减少潜在的 bug,提高团队协作效率。
更多推荐


所有评论(0)