前端开发
TypeScript 基础概念详解
深入了解 TypeScript 的基础概念,包括类型注解、接口、泛型等核心特性,为初学者提供完整的入门指导。
Zee
2024-01-15
12分钟
3 个标签
TypeScriptJavaScript类型系统
TypeScript 基础概念详解
TypeScript 是 JavaScript 的超集,为 JavaScript 添加了静态类型检查。本文将详细介绍 TypeScript 的核心概念。
为什么选择 TypeScript?
1. 类型安全
TypeScript 在编译时就能发现类型错误,而不是在运行时:
typescript// JavaScript - 运行时才会发现错误
function greet(name) {
return "Hello, " + name.toUpperCase();
}
greet(123); // 运行时错误
// TypeScript - 编译时就能发现错误
function greet(name: string): string {
return "Hello, " + name.toUpperCase();
}
greet(123); // 编译时错误:Argument of type 'number' is not assignable to parameter of type 'string'
2. 更好的开发体验
- 智能代码补全
- 重构支持
- 导航和搜索
基础类型
原始类型
typescriptlet name: string = "张三";
let age: number = 25;
let isStudent: boolean = true;
let nothing: null = null;
let notDefined: undefined = undefined;
数组类型
typescript// 两种写法都可以
let numbers: number[] = [1, 2, 3];
let strings: Array<string> = ["a", "b", "c"];
对象类型
typescript// 直接定义
let person: { name: string; age: number } = {
name: "李四",
age: 30
};
// 使用接口定义
interface Person {
name: string;
age: number;
email?: string; // 可选属性
}
let user: Person = {
name: "王五",
age: 28
};
接口 (Interface)
接口是 TypeScript 的核心概念之一,用于定义对象的结构:
typescriptinterface BlogPost {
id: number;
title: string;
content: string;
author: string;
publishDate: Date;
tags: string[];
isPublished: boolean;
}
// 使用接口
const post: BlogPost = {
id: 1,
title: "我的第一篇博客",
content: "这是文章内容...",
author: "张三",
publishDate: new Date(),
tags: ["TypeScript", "前端"],
isPublished: true
};
接口继承
typescriptinterface Animal {
name: string;
age: number;
}
interface Dog extends Animal {
breed: string;
bark(): void;
}
const myDog: Dog = {
name: "小白",
age: 3,
breed: "金毛",
bark() {
console.log("汪汪汪!");
}
};
函数类型
函数参数和返回值类型
typescript// 基础函数类型
function add(a: number, b: number): number {
return a + b;
}
// 箭头函数
const multiply = (a: number, b: number): number => a * b;
// 可选参数
function greet(name: string, title?: string): string {
if (title) {
return `Hello, ${title} ${name}`;
}
return `Hello, ${name}`;
}
// 默认参数
function createUser(name: string, role: string = "user"): object {
return { name, role };
}
函数重载
typescriptfunction format(value: string): string;
function format(value: number): string;
function format(value: string | number): string {
if (typeof value === "string") {
return value.toUpperCase();
}
return value.toFixed(2);
}
泛型 (Generics)
泛型让我们能够创建可重用的组件:
typescript// 基础泛型函数
function identity<T>(arg: T): T {
return arg;
}
let output1 = identity<string>("hello"); // string
let output2 = identity<number>(42); // number
// 泛型接口
interface ApiResponse<T> {
data: T;
status: number;
message: string;
}
// 使用泛型接口
const userResponse: ApiResponse<Person> = {
data: { name: "张三", age: 25 },
status: 200,
message: "success"
};
const postResponse: ApiResponse<BlogPost[]> = {
data: [post],
status: 200,
message: "success"
};
泛型约束
typescriptinterface Lengthwise {
length: number;
}
function logLength<T extends Lengthwise>(arg: T): T {
console.log(arg.length);
return arg;
}
logLength("hello"); // ✓ 字符串有 length 属性
logLength([1, 2, 3]); // ✓ 数组有 length 属性
logLength(123); // ✗ 数字没有 length 属性
联合类型和交叉类型
联合类型 (Union Types)
typescripttype StringOrNumber = string | number;
type Status = "pending" | "approved" | "rejected";
function formatId(id: StringOrNumber): string {
if (typeof id === "string") {
return id.toUpperCase();
}
return id.toString();
}
let currentStatus: Status = "pending"; // ✓
// currentStatus = "invalid"; // ✗ 不是有效的状态值
交叉类型 (Intersection Types)
typescriptinterface Colorful {
color: string;
}
interface Circle {
radius: number;
}
type ColorfulCircle = Colorful & Circle;
const cc: ColorfulCircle = {
color: "red",
radius: 42
};
实用工具类型
TypeScript 提供了许多内置的工具类型:
typescriptinterface User {
id: number;
name: string;
email: string;
age: number;
}
// Pick - 选择部分属性
type UserPreview = Pick<User, 'id' | 'name'>;
// Omit - 排除部分属性
type CreateUser = Omit<User, 'id'>;
// Partial - 所有属性变为可选
type UpdateUser = Partial<User>;
// Required - 所有属性变为必需
type CompleteUser = Required<User>;
// Record - 创建键值对类型
type UserRoles = Record<string, string>;
const roles: UserRoles = {
admin: "管理员",
user: "普通用户",
guest: "访客"
};
类型断言
有时我们比 TypeScript 更了解某个值的类型:
typescript// 类型断言的两种语法
let someValue: unknown = "this is a string";
let strLength1: number = (someValue as string).length;
let strLength2: number = (<string>someValue).length;
// 在 JSX 中只能使用 as 语法
// let strLength = (<string>someValue).length; // 会与 JSX 语法冲突
最佳实践
1. 优先使用类型推断
typescript// 好的做法
let name = "张三"; // TypeScript 自动推断为 string
let numbers = [1, 2, 3]; // 推断为 number[]
// 不必要的类型注解
let name: string = "张三";
let numbers: number[] = [1, 2, 3];
2. 使用严格模式
在 tsconfig.json
中启用严格模式:
json{
"compilerOptions": {
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true
}
}
3. 为函数参数和返回值添加类型
typescript// 清晰的函数签名
function processUser(user: User): UserPreview {
return {
id: user.id,
name: user.name
};
}
总结
TypeScript 为 JavaScript 开发带来了以下优势:
- 类型安全:编译时捕获错误
- 更好的 IDE 支持:代码补全、重构、导航
- 代码自文档化:类型即文档
- 重构信心:大规模重构更安全
- 团队协作:接口定义让团队协作更顺畅
掌握了这些基础概念,你就能够开始使用 TypeScript 开发更健壮的应用了。在实际项目中,建议从简单的类型注解开始,逐步学习更高级的特性。