TypeScript 简介
TypeScript 是 JavaScript 的超集,它添加了可选的静态类型和基于类的面向对象编程。TypeScript 由微软开发和维护,设计目标是开发大型应用。
常用点
- 类型判断
- as 断言
- interface
- record 用法
- keyof typeof
- 类,class,type,enum 枚举
1. 基本类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| let isDone: boolean = false;
let decimal: number = 6; let hex: number = 0xf00d;
let color: string = "blue"; let sentence: string = `The color is ${color}`;
let list: number[] = [1, 2, 3]; let list2: Array<number> = [1, 2, 3];
let x: [string, number] = ["hello", 10];
|
2. 特殊类型
1 2 3 4 5 6 7 8 9 10 11 12
| let notSure: any = 4; notSure = "maybe a string";
function warnUser(): void { console.log("This is a warning message"); }
let u: undefined = undefined; let n: null = null;
|
接口(Interfaces)
接口是 TypeScript 的一个核心概念,它定义了对象的结构:
1 2 3 4 5 6 7 8 9 10 11 12
| interface User { name: string; age: number; email?: string; readonly id: number; }
let user: User = { name: "Tom", age: 25, id: 1 };
|
类(Classes)
TypeScript 提供了完整的面向对象编程特性:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class Animal { private name: string; constructor(name: string) { this.name = name; } move(distance: number = 0) { console.log(`${this.name} moved ${distance}m.`); } }
class Dog extends Animal { bark() { console.log('Woof! Woof!'); } }
|
泛型(Generics)
泛型允许我们编写可重用的代码:
1 2 3 4 5
| function identity<T>(arg: T): T { return arg; }
let output = identity<string>("myString");
|
Type 与 Interface 的比较
TypeScript 中的 type 和 interface 都可以用来定义类型,但它们有一些重要的区别:
Interface
- 扩展性
1 2 3 4 5 6 7
| interface Animal { name: string }
interface Bear extends Animal { honey: boolean }
|
- 自动合并
1 2 3 4 5 6 7 8 9 10 11 12 13
| interface User { name: string }
interface User { age: number }
|
Type
- 类型别名
1 2 3 4 5 6 7 8 9 10 11 12
| type Point = { x: number; y: number; };
type ID = number | string;
type Partial<T> = { [P in keyof T]?: T[P]; };
|
- 无法重复声明
1 2 3 4 5 6 7 8
| type User = { name: string }
type User = { age: number }
|
主要区别
扩展方式
- interface 使用 extends
- type 使用 & 交叉类型
合并声明
- interface 支持自动合并
- type 不支持重复声明
使用场景
- interface:定义对象结构
- type:需要使用联合类型、交叉类型时
Record 工具类型
Record 是 TypeScript 中一个非常实用的工具类型,用于创建一个对象类型,其属性键为 K,属性值为 T。
1. 基本用法
1 2 3 4 5 6 7 8 9 10 11 12 13
| type PageInfo = Record<string, string>;
type PageInfo = { [key: string]: string; }
const page: PageInfo = { title: "Home", description: "Welcome to our site" };
|
2. 限定键名
1 2 3 4 5 6 7 8 9 10
| type Roles = "admin" | "user" | "guest"; type UserRoles = Record<Roles, boolean>;
const userAccess: UserRoles = { admin: true, user: true, guest: false };
|
3. 复杂类型
1 2 3 4 5 6 7 8 9 10 11 12 13
| interface UserInfo { name: string; age: number; }
type UsersDatabase = Record<string, UserInfo>;
const users: UsersDatabase = { "user1": { name: "John", age: 30 }, "user2": { name: "Jane", age: 25 } };
|
4. 实践应用
- 状态管理
1 2 3 4 5 6 7
| type LoadingState = Record<string, boolean>;
const pageLoadingState: LoadingState = { userProfile: true, settings: false, notifications: true };
|
- API 响应处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| type ApiResponse<T> = Record<string, { data: T; loading: boolean; error: Error | null; }>;
interface User { id: number; name: string; }
const apiState: ApiResponse<User> = { userProfile: { data: { id: 1, name: "John" }, loading: false, error: null } };
|
- 配置对象
1 2 3 4 5 6 7 8 9 10
| type Config = Record<string, { enabled: boolean; value: string | number; }>;
const appConfig: Config = { theme: { enabled: true, value: "dark" }, language: { enabled: true, value: "en" }, notifications: { enabled: false, value: 0 } };
|
Omit 工具类型
Omit 是 TypeScript 中的一个实用工具类型,用于从一个类型中剔除指定的属性,创建一个新的类型。
1. 基本用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| interface User { id: number; name: string; email: string; password: string; }
type PublicUser = Omit<User, 'password'>;
|
2. 剔除多个属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| interface Product { id: number; name: string; price: number; stock: number; createTime: Date; updateTime: Date; }
type ProductBasicInfo = Omit<Product, 'createTime' | 'updateTime'>;
const product: ProductBasicInfo = { id: 1, name: "iPhone", price: 999, stock: 100 };
|
3. 实践应用
- API 请求参数处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| interface UserCreateParams { name: string; email: string; password: string; id: number; createTime: Date; }
type UserCreate = Omit<UserCreateParams, 'id' | 'createTime'>;
function createUser(user: UserCreate) { }
|
- 表单数据处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| interface FormData { username: string; password: string; confirmPassword: string; token: string; }
type SubmitData = Omit<FormData, 'confirmPassword' | 'token'>;
function submitForm(data: FormData) { const submitData: SubmitData = { username: data.username, password: data.password }; }
|
- 与其他工具类型组合
1 2 3 4 5 6 7 8 9 10 11 12 13
| interface User { id: number; name: string; email: string; password: string; }
type UpdateUserParams = Partial<Omit<User, 'id'>>;
function updateUser(userId: number, data: UpdateUserParams) { }
|
类型断言
类型断言用于告诉编译器”相信我,我知道自己在做什么”。
1. 基本语法
1 2 3 4 5 6 7
| let someValue: any = "this is a string"; let strLength: number = (<string>someValue).length;
let someValue: any = "this is a string"; let strLength: number = (someValue as string).length;
|
2. 常见用途
- 断言具体类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| interface Cat { name: string; run(): void; }
interface Fish { name: string; swim(): void; }
function isFish(animal: Cat | Fish) { if (typeof (animal as Fish).swim === 'function') { return true; } return false; }
|
- 断言为 unknown
1 2
| let foo = 'hello'; (foo as unknown as number).toFixed(2);
|
- 非空断言
1 2 3 4
| function processName(name?: string) { console.log(name!.toUpperCase()); }
|
- 使用枚举来表示固定选项
1 2 3 4 5 6
| enum Direction { Up = "UP", Down = "DOWN", Left = "LEFT", Right = "RIGHT" }
|
注意事项
类型断言不是类型转换
- 断言只会影响 TypeScript 编译时的类型检查
- 不会真的改变变量的类型
断言限制
- 只能断言为更具体或更不具体的类型
- 不能随意断言不相关的类型
最佳实践
- 尽量避免使用类型断言
- 优先使用类型声明和类型推断
- 必要时才使用类型断言
实践建议
始终启用严格模式
1 2 3 4 5
| { "compilerOptions": { "strict": true } }
|
善用类型推断
- 不要过度注解类型
- 让 TypeScript 自动推断简单类型
接口优于类型别名
使用枚举来表示固定选项
1 2 3 4 5 6
| enum Direction { Up = "UP", Down = "DOWN", Left = "LEFT", Right = "RIGHT" }
|
总结
TypeScript 通过添加类型系统,极大地提升了 JavaScript 开发的体验和代码质量。它不仅提供了更好的开发工具支持,还能帮助我们在开发阶段就发现潜在的问题。合理使用 interface、type、类型断言和工具类型(如 Record、Omit),可以让我们的代码更加健壮和可维护。对于大型项目来说,TypeScript 是一个非常值得考虑的选择。