𝑻𝒆𝒏𝑪𝒍𝒂𝒘正在头脑风暴···
𝑻𝒆𝒏𝑲𝒊𝑺𝒆𝒀𝒂の𝑨𝒈𝒆𝒏𝒕助手
𝑻𝒆𝒏-𝒇𝒍𝒂𝒔𝒉

TypeScript 类型系统深入

TypeScript 是 JavaScript 的超集,通过静态类型系统为开发者提供了更好的开发体验和代码质量。本文将深入探讨 TypeScript 的类型系统核心概念和高级用法。

基础类型

1. 基本类型

// 原始类型
let name: string = "TypeScript";
let age: number = 25;
let isStudent: boolean = true;
let empty: null = null;
let notDefined: undefined = undefined;

// 特殊类型
let bigInt: bigint = 9007199254740991n;
let symbol: symbol = Symbol("unique");

// 数组类型
let numbers: number[] = [1, 2, 3];
let strings: Array<string> = ["a", "b", "c"];

// 元组类型
let tuple: [string, number] = ["hello", 123];

// 枚举类型
enum Color {
Red,
Green,
Blue
}

const color: Color = Color.Red;

2. 对象类型

// 对象类型字面量
let person: {
name: string;
age: number;
hobbies: string[];
} = {
name: "Alice",
age: 30,
hobbies: ["reading", "coding"]
};

// 接口定义
interface Person {
name: string;
age?: number; // 可选属性
readonly id: string; // 只读属性
[key: string]: any; // 索引签名
}

const person: Person = {
name: "Bob",
id: "123"
};

3. 函数类型

// 函数声明
function add(a: number, b: number): number {
return a + b;
}

// 函数表达式
const multiply: (a: number, b: number) => number = (a, b) => a * b;

// 箭头函数
const divide = (a: number, b: number): number => a / b;

// 可选参数
function greet(name: string, greeting?: string): string {
return `${greeting || "Hello"}, ${name}!`;
}

// 默认参数
function createPoint(x: number = 0, y: number = 0): { x: number; y: number } {
return { x, y };
}

// 剩余参数
function sum(...numbers: number[]): number {
return numbers.reduce((acc, curr) => acc + curr, 0);
}

高级类型

1. 联合类型

// 基本联合类型
let value: string | number;
value = "hello";
value = 42;

// 字面量联合类型
type Direction = "up" | "down" | "left" | "right";

function move(direction: Direction): void {
console.log(`Moving ${direction}`);
}

// 类型保护
function processValue(value: string | number): string {
if (typeof value === "string") {
return value.toUpperCase();
}
return value.toString();
}

// 类型断言
function getValue(): string | number {
return Math.random() > 0.5 ? "hello" : 42;
}

const result = getValue() as string;

2. 交叉类型

type Person = {
name: string;
age: number;
};

type Employee = {
id: string;
department: string;
};

type EmployeeWithPerson = Person & Employee;

const employee: EmployeeWithPerson = {
name: "Alice",
age: 30,
id: "123",
department: "Engineering"
};

// 实用交叉类型
type Nullable<T> = T | null;
type Optional<T> = T | undefined;
type Maybe<T> = Nullable<Optional<T>>;

3. 泛型

// 基础泛型
function identity<T>(arg: T): T {
return arg;
}

const result1 = identity<string>("hello");
const result2 = identity(42); // 类型推断

// 数组操作
function first<T>(array: T[]): T | undefined {
return array[0];
}

function last<T>(array: T[]): T | undefined {
return array[array.length - 1];
}

// 约束泛型
interface Lengthwise {
length: number;
}

function logLength<T extends Lengthwise>(arg: T): T {
console.log(arg.length);
return arg;
}

logLength("hello"); // 有效
logLength([1, 2, 3]); // 有效
logLength({ length: 42 }); // 有效
// logLength(123); // 错误:没有 length 属性

// 泛型接口
interface Container<T> {
value: T;
}

const numberContainer: Container<number> = { value: 123 };
const stringContainer: Container<string> = { value: "hello" };

4. 类型别名和映射类型

// 类型别名
type Point = {
x: number;
y: number;
};

type ID = string | number;

// 映射类型
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};

type Optional<T> = {
[P in keyof T]?: T[P];
};

// 实际使用
type User = {
name: string;
age: number;
email: string;
};

type ReadonlyUser = Readonly<User>;
type PartialUser = Partial<User>;
type OptionalUser = Optional<User>;

// 工具类型
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};

type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;

type UserWithoutEmail = Omit<User, "email">;
type UserNameAndAge = Pick<User, "name" | "age">;

5. 条件类型

// 基础条件类型
type ExtractType<T, U> = T extends U ? T : never;
type ExcludeType<T, U> = T extends U ? never : T;

type StringOrNumber = string | number;
type StringOnly = ExtractType<StringOrNumber, string>;
type NumberOnly = ExcludeType<StringOrNumber, string>;

// 实用条件类型
type NonNullable<T> = T extends null | undefined ? never : T;
type ReturnType<T extends (...args: any[]) => any> = T extends (...args: any) => infer R ? R : any;

// 分布式条件类型
type ToArray<T> = T extends any ? T[] : never;
type Str = ToArray<string>; // string[]
type Num = ToArray<number>; // number[]
type Both = ToArray<string | number>; // string[] | number[]

高级类型操作

1. 类型推断

// 隐式类型推断
let inferredArray = [1, 2, 3]; // number[]
let inferredObject = { name: "Alice", age: 30 }; // { name: string; age: number }

// 类型参数推断
function map<T, U>(array: T[], fn: (item: T) => U): U[] {
return array.map(fn);
}

const numbers = [1, 2, 3];
const doubled = map(numbers, x => x * 2); // number[]

// 复杂类型推断
const complexObject = {
name: "Alice",
age: 30,
address: {
street: "123 Main St",
city: "New York"
}
};

const street = complexObject.address.street; // string

2. 类型守卫

// typeof 守卫
function isString(value: any): value is string {
return typeof value === "string";
}

function processValue(value: string | number): string {
if (isString(value)) {
return value.toUpperCase();
}
return value.toString();
}

// instanceof 守卫
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
}

class Dog extends Animal {
bark() {
return "Woof!";
}
}

function isDog(animal: Animal): animal is Dog {
return "bark" in animal;
}

// 自定义类型守卫
interface Square {
kind: "square";
size: number;
}

interface Circle {
kind: "circle";
radius: number;
}

type Shape = Square | Circle;

function isSquare(shape: Shape): shape is Square {
return shape.kind === "square";
}

3. 类型断言和类型收窄

// 类型断言
const myCanvas = document.getElementById("main_canvas") as HTMLCanvasElement;

// 非空断言
function nonNullAssertion<T>(value: T): NonNullable<T> {
return value!;
}

// 类型收窄
type NetworkLoadedState = {
state: "loaded";
data: any;
};

type NetworkErrorState = {
state: "error";
error: string;
};

type NetworkState = NetworkLoadedState | NetworkErrorState;

function handleNetworkState(state: NetworkState) {
if (state.state === "loaded") {
console.log(state.data);
} else {
console.error(state.error);
}
}

实用类型工具

1. 常用工具类型

// Partial
interface User {
name: string;
age: number;
email: string;
}

type PartialUser = Partial<User>;
// 相当于 { name?: string; age?: number; email?: string; }

// Required
type RequiredUser = Required<User>;
// 相当于 { name: string; age: number; email: string; }

// Readonly
type ReadonlyUser = Readonly<User>;
// 相当于 { readonly name: string; readonly age: number; readonly email: string; }

// Record
type UserRoles = Record<"admin" | "user" | "guest", string>;
// 相当于 { admin: string; user: string; guest: string; }

// Pick
type UserName = Pick<User, "name">;
// 相当于 { name: string; }

// Omit
type UserWithoutEmail = Omit<User, "email">;
// 相当于 { name: string; age: number; }

// Extract
type Extracted = Extract<string | number | boolean, string>;
// 相当于 string

// Exclude
type Excluded = Exclude<string | number | boolean, string>;
// 相当于 number | boolean

2. 自定义工具类型

// 深度 Partial
type DeepPartial<T> = {
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};

interface NestedObject {
name: string;
address: {
street: string;
city: string;
};
}

type DeepPartialNested = DeepPartial<NestedObject>;

// 深度 Readonly
type DeepReadonly<T> = {
readonly [P in keyof T]: T[P] extends object ? DeepReadonly<T[P]> : T[P];
};

// 获取对象的所有路径
type Paths<T> = T extends object
? {
[K in keyof T]: K | `${K}.${Paths<T[K]>}`;
}[keyof T]
: never;

interface Nested {
a: number;
b: {
c: string;
d: {
e: boolean;
};
};
}

type NestedPaths = Paths<Nested>;
// 相当于 "a" | "b" | "b.c" | "b.d" | "b.d.e"

// 可选函数参数
type OptionalFunction<T extends (...args: any[]) => any> = (
...args: Parameters<T>
) => ReturnType<T>;

// 函数重载
function process(value: string): string;
function process(value: number): number;
function process(value: string | number): string | number {
if (typeof value === "string") {
return value.toUpperCase();
}
return value * 2;
}

类型系统最佳实践

1. 类型设计原则

// 1. 明确性
// 好的设计
interface User {
id: string;
name: string;
email: string;
role: "admin" | "user" | "guest";
}

// 不好的设计
interface User {
id: string | number;
name: string;
email?: string;
role: any;
}

// 2. 可组合性
// 使用组合而不是继承
interface Animal {
name: string;
}

interface Bird extends Animal {
fly(): void;
}

interface Fish extends Animal {
swim(): void;
}

// 更好的方式
interface Bird {
name: string;
fly(): void;
}

interface Fish {
name: string;
swim(): void;
}

// 3. 泛型复用
interface Container<T> {
value: T;
get(): T;
set(value: T): void;
}

class NumberContainer implements Container<number> {
value: number;

constructor(value: number) {
this.value = value;
}

get(): number {
return this.value;
}

set(value: number): void {
this.value = value;
}
}

2. 错误处理和类型安全

// 类型安全的错误处理
class Result<T, E = Error> {
constructor(
public readonly ok: boolean,
public readonly value?: T,
public readonly error?: E
) {}

static success<T, E = Error>(value: T): Result<T, E> {
return new Result(true, value);
}

static failure<T, E = Error>(error: E): Result<T, E> {
return new Result(false, undefined, error);
}

map<U>(fn: (value: T) => U): Result<U, E> {
if (this.ok) {
return Result.success(fn(this.value!));
}
return Result.failure(this.error!);
}
}

// 使用示例
function fetchUser(id: number): Result<User, Error> {
try {
const user = { id, name: "Alice" };
return Result.success(user);
} catch (error) {
return Result.failure(error as Error);
}
}

const result = fetchUser(1);
result.map(user => user.name.toUpperCase());

3. 性能优化

// 避免过度使用类型推断
// 不好的方式
function processData(data: { name: string; age: number; email: string }) {
// 处理逻辑
}

// 好的方式
interface User {
name: string;
age: number;
email: string;
}

function processData(data: User) {
// 处理逻辑
}

// 使用类型别名简化复杂类型
type UserPreferences = {
theme: "light" | "dark";
language: "en" | "zh" | "ja";
notifications: boolean;
fontSize: number;
};

// 使用映射类型创建变体
type UserPreferencesPartial = Partial<UserPreferences>;
type UserPreferencesRequired = Required<UserPreferences>;
type UserPreferencesReadonly = Readonly<UserPreferences>;

实际应用场景

1. API 响应类型定义

interface ApiResponse<T> {
data: T;
success: boolean;
message?: string;
timestamp: Date;
}

interface User {
id: string;
name: string;
email: string;
avatar?: string;
}

// API 调用示例
async function fetchUsers(): Promise<ApiResponse<User[]>> {
const response = await fetch('/api/users');
return response.json();
}

// 使用示例
fetchUsers().then(response => {
if (response.success) {
const users = response.data;
console.log(users.map(user => user.name));
}
});

2. 状态管理类型

// Redux 状态类型
interface AppState {
user: User;
posts: Post[];
loading: boolean;
error: string | null;
}

interface Action {
type: string;
payload?: any;
}

function reducer(state: AppState, action: Action): AppState {
switch (action.type) {
case 'SET_USER':
return { ...state, user: action.payload };
case 'SET_LOADING':
return { ...state, loading: action.payload };
case 'SET_ERROR':
return { ...state, error: action.payload };
default:
return state;
}
}

// 使用类型保护
function isUserAction(action: Action): action is { type: 'SET_USER'; payload: User } {
return action.type === 'SET_USER';
}

function isSetErrorAction(action: Action): action is { type: 'SET_ERROR'; payload: string } {
return action.type === 'SET_ERROR';
}

// 类型安全的 dispatch
function dispatch<T extends Action>(action: T): void {
const newState = reducer(state, action);
// 更新状态逻辑
}

3. 组件属性类型

// React 组件属性类型
interface ButtonProps {
children: React.ReactNode;
variant?: "primary" | "secondary" | "danger";
size?: "small" | "medium" | "large";
onClick?: () => void;
disabled?: boolean;
className?: string;
}

const Button: React.FC<ButtonProps> = ({
children,
variant = "primary",
size = "medium",
onClick,
disabled = false,
className = ""
}) => {
const classes = `btn btn-${variant} btn-${size} ${disabled ? 'disabled' : ''} ${className}`;

return (
<button
className={classes}
onClick={onClick}
disabled={disabled}
>
{children}
</button>
);
};

// 使用示例
const App: React.FC = () => {
return (
<div>
<Button variant="primary" onClick={() => console.log('Clicked')}>
Click Me
</Button>
<Button variant="danger" disabled>
Disabled Button
</Button>
</div>
);
};

总结

TypeScript 的类型系统非常强大,掌握它可以带来以下好处:

  1. 类型安全:在编译时发现错误,减少运行时错误
  2. 代码可读性:清晰的类型定义让代码更容易理解
  3. 开发体验:IDE 提供智能提示和自动补全
  4. 重构支持:类型安全的重构

关键要点:

  • 善用基础类型和高级类型
  • 理解类型推断和类型守卫
  • 创建可复用的工具类型
  • 遵循类型设计原则
  • 在实际项目中灵活应用

通过合理使用 TypeScript 的类型系统,可以构建更加健壮、可维护的应用程序。