Skip to content

类型系统

类型注解

Python 类型注解

基本类型注解

python
# Python - 基本类型注解
from typing import List, Dict, Optional, Union, Any

# 变量类型注解
name: str = "Alice"
age: int = 25
height: float = 1.75
is_student: bool = True

# 函数参数和返回值类型注解
def greet(name: str) -> str:
    return f"Hello, {name}!"

def add_numbers(a: int, b: int) -> int:
    return a + b

def calculate_average(numbers: List[float]) -> float:
    if not numbers:
        return 0.0
    return sum(numbers) / len(numbers)

# 复杂类型注解
def process_user_data(
    user_id: int,
    name: str,
    age: Optional[int] = None,
    hobbies: List[str] = None
) -> Dict[str, Any]:
    result = {
        "id": user_id,
        "name": name,
        "age": age,
        "hobbies": hobbies or []
    }
    return result

# 使用类型注解
result = greet("Bob")  # 类型检查器会验证参数类型
print(result)  # Hello, Bob!

numbers = [1.5, 2.5, 3.5]
avg = calculate_average(numbers)
print(f"平均值: {avg}")  # 平均值: 2.5

user_data = process_user_data(1, "Charlie", 30, ["reading", "coding"])
print(user_data)

高级类型注解

python
# Python - 高级类型注解
from typing import (
    List, Dict, Optional, Union, Any, Tuple,
    Callable, TypeVar, Generic, Protocol
)

# Union 类型(联合类型)
def process_data(data: Union[str, int, float]) -> str:
    return str(data)

# 使用 | 语法(Python 3.10+)
def process_data_v2(data: str | int | float) -> str:
    return str(data)

# Optional 类型
def get_user_age(user_id: int) -> Optional[int]:
    # 模拟数据库查询
    users = {1: 25, 2: 30}
    return users.get(user_id)

# Callable 类型
def apply_operation(
    func: Callable[[int, int], int],
    a: int,
    b: int
) -> int:
    return func(a, b)

def add(a: int, b: int) -> int:
    return a + b

def multiply(a: int, b: int) -> int:
    return a * b

# 使用 Callable
result1 = apply_operation(add, 5, 3)      # 8
result2 = apply_operation(multiply, 5, 3) # 15

# 泛型类型
T = TypeVar('T')

class Stack(Generic[T]):
    def __init__(self) -> None:
        self.items: List[T] = []

    def push(self, item: T) -> None:
        self.items.append(item)

    def pop(self) -> T:
        if not self.items:
            raise IndexError("Stack is empty")
        return self.items.pop()

    def peek(self) -> Optional[T]:
        return self.items[-1] if self.items else None

# 使用泛型
int_stack = Stack[int]()
int_stack.push(1)
int_stack.push(2)
print(int_stack.pop())  # 2

str_stack = Stack[str]()
str_stack.push("hello")
str_stack.push("world")
print(str_stack.pop())  # world

类型别名和 Protocol

python
# Python - 类型别名和 Protocol
from typing import TypeAlias, Protocol

# 类型别名
UserId = int
UserName = str
UserAge = int
UserData = Dict[str, Union[str, int, List[str]]]

# 使用类型别名
def create_user(user_id: UserId, name: UserName, age: UserAge) -> UserData:
    return {
        "id": user_id,
        "name": name,
        "age": age,
        "hobbies": []
    }

# Protocol(结构类型)
class Drawable(Protocol):
    def draw(self) -> str:
        ...

class Circle:
    def __init__(self, radius: float):
        self.radius = radius

    def draw(self) -> str:
        return f"Drawing circle with radius {self.radius}"

class Rectangle:
    def __init__(self, width: float, height: float):
        self.width = width
        self.height = height

    def draw(self) -> str:
        return f"Drawing rectangle {self.width}x{self.height}"

def draw_shape(shape: Drawable) -> str:
    return shape.draw()

# 使用 Protocol
circle = Circle(5.0)
rectangle = Rectangle(10.0, 5.0)

print(draw_shape(circle))     # Drawing circle with radius 5.0
print(draw_shape(rectangle))  # Drawing rectangle 10.0x5.0

JavaScript 类型注解(TypeScript)

基本类型注解

typescript
// TypeScript - 基本类型注解
// 变量类型注解
let name: string = "Alice";
let age: number = 25;
let height: number = 1.75;
let isStudent: boolean = true;

// 函数参数和返回值类型注解
function greet(name: string): string {
  return `Hello, ${name}!`;
}

function addNumbers(a: number, b: number): number {
  return a + b;
}

function calculateAverage(numbers: number[]): number {
  if (numbers.length === 0) {
    return 0;
  }
  return numbers.reduce((sum, num) => sum + num, 0) / numbers.length;
}

// 复杂类型注解
interface UserData {
  id: number;
  name: string;
  age?: number; // 可选属性
  hobbies: string[];
}

function processUserData(
  userId: number,
  name: string,
  age?: number,
  hobbies: string[] = []
): UserData {
  return {
    id: userId,
    name,
    age,
    hobbies,
  };
}

// 使用类型注解
const result = greet("Bob");
console.log(result); // Hello, Bob!

const numbers = [1.5, 2.5, 3.5];
const avg = calculateAverage(numbers);
console.log(`平均值: ${avg}`); // 平均值: 2.5

const userData = processUserData(1, "Charlie", 30, ["reading", "coding"]);
console.log(userData);

高级类型注解

typescript
// TypeScript - 高级类型注解

// Union 类型
function processData(data: string | number | boolean): string {
  return String(data);
}

// 可选类型
function getUserAge(userId: number): number | undefined {
  // 模拟数据库查询
  const users: Record<number, number> = { 1: 25, 2: 30 };
  return users[userId];
}

// 函数类型
type BinaryOperation = (a: number, b: number) => number;

function applyOperation(func: BinaryOperation, a: number, b: number): number {
  return func(a, b);
}

function add(a: number, b: number): number {
  return a + b;
}

function multiply(a: number, b: number): number {
  return a * b;
}

// 使用函数类型
const result1 = applyOperation(add, 5, 3); // 8
const result2 = applyOperation(multiply, 5, 3); // 15

// 泛型类型
class Stack<T> {
  private items: T[] = [];

  push(item: T): void {
    this.items.push(item);
  }

  pop(): T {
    if (this.items.length === 0) {
      throw new Error("Stack is empty");
    }
    return this.items.pop()!;
  }

  peek(): T | undefined {
    return this.items[this.items.length - 1];
  }
}

// 使用泛型
const intStack = new Stack<number>();
intStack.push(1);
intStack.push(2);
console.log(intStack.pop()); // 2

const strStack = new Stack<string>();
strStack.push("hello");
strStack.push("world");
console.log(strStack.pop()); // world

接口和类型别名

typescript
// TypeScript - 接口和类型别名

// 接口定义
interface User {
  id: number;
  name: string;
  age?: number;
  email: string;
}

interface Employee extends User {
  department: string;
  salary: number;
}

// 类型别名
type UserId = number;
type UserName = string;
type UserAge = number;

type UserData = {
  id: UserId;
  name: UserName;
  age?: UserAge;
  hobbies: string[];
};

// 联合类型
type Status = "pending" | "approved" | "rejected";

// 函数类型
type EventHandler = (event: Event) => void;
type AsyncFunction<T> = () => Promise<T>;

// 使用接口和类型
function createUser(userData: UserData): User {
  return {
    id: userData.id,
    name: userData.name,
    age: userData.age,
    email: `${userData.name.toLowerCase()}@example.com`,
  };
}

function createEmployee(
  user: User,
  department: string,
  salary: number
): Employee {
  return {
    ...user,
    department,
    salary,
  };
}

// 使用示例
const userData: UserData = {
  id: 1,
  name: "Alice",
  age: 25,
  hobbies: ["reading", "coding"],
};

const user = createUser(userData);
const employee = createEmployee(user, "Engineering", 75000);

console.log(user);
console.log(employee);

类型检查工具

Python 类型检查

mypy 配置

ini
# mypy.ini 配置文件
[mypy]
python_version = 3.9
warn_return_any = True
warn_unused_configs = True
disallow_untyped_defs = True
disallow_incomplete_defs = True
check_untyped_defs = True
disallow_untyped_decorators = True
no_implicit_optional = True
warn_redundant_casts = True
warn_unused_ignores = True
warn_no_return = True
warn_unreachable = True
strict_equality = True

[mypy.plugins.numpy.*]
ignore_missing_imports = True

[mypy-pandas.*]
ignore_missing_imports = True

使用 mypy

bash
# 安装 mypy
pip install mypy

# 检查单个文件
mypy myfile.py

# 检查整个项目
mypy src/

# 生成报告
mypy --html-report reports/ src/

# 忽略错误
mypy --ignore-missing-imports src/

TypeScript 类型检查

tsconfig.json 配置

json
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "lib": ["ES2020"],
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true,
    "removeComments": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "noImplicitThis": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "moduleResolution": "node",
    "baseUrl": "./",
    "paths": {
      "@/*": ["src/*"]
    },
    "allowSyntheticDefaultImports": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist", "**/*.test.ts"]
}

使用 TypeScript 编译器

bash
# 安装 TypeScript
npm install -g typescript

# 编译 TypeScript 文件
tsc src/index.ts

# 编译整个项目
tsc

# 监视模式
tsc --watch

# 生成声明文件
tsc --declaration

# 检查类型错误
tsc --noEmit

类型注解最佳实践

Python 最佳实践

python
# Python - 类型注解最佳实践
from typing import (
    List, Dict, Optional, Union, Any, Tuple,
    Callable, TypeVar, Generic, Protocol, Final
)
from dataclasses import dataclass

# 使用 dataclass 简化类定义
@dataclass
class User:
    id: int
    name: str
    email: str
    age: Optional[int] = None
    is_active: bool = True

# 使用 Final 标记常量
MAX_RETRY_COUNT: Final[int] = 3
DEFAULT_TIMEOUT: Final[float] = 30.0

# 类型别名提高可读性
UserId = int
UserName = str
UserEmail = str

# 使用 Protocol 定义接口
class DataProcessor(Protocol):
    def process(self, data: List[Any]) -> Dict[str, Any]:
        ...

class UserProcessor:
    def process(self, data: List[User]) -> Dict[str, Any]:
        return {
            "count": len(data),
            "active_users": len([u for u in data if u.is_active]),
            "average_age": sum(u.age or 0 for u in data) / len(data) if data else 0
        }

# 泛型函数
T = TypeVar('T')

def find_item(items: List[T], predicate: Callable[[T], bool]) -> Optional[T]:
    for item in items:
        if predicate(item):
            return item
    return None

# 使用示例
users = [
    User(1, "Alice", "alice@example.com", 25),
    User(2, "Bob", "bob@example.com", 30),
    User(3, "Charlie", "charlie@example.com", 35, False)
]

# 查找活跃用户
active_user = find_item(users, lambda u: u.is_active)
print(active_user)  # User(id=1, name='Alice', ...)

# 处理用户数据
processor = UserProcessor()
result = processor.process(users)
print(result)  # {'count': 3, 'active_users': 2, 'average_age': 30.0}

TypeScript 最佳实践

typescript
// TypeScript - 类型注解最佳实践

// 使用 const assertions
const MAX_RETRY_COUNT = 3 as const;
const DEFAULT_TIMEOUT = 30.0 as const;

// 类型别名
type UserId = number;
type UserName = string;
type UserEmail = string;

// 接口定义
interface User {
  readonly id: UserId;
  name: UserName;
  email: UserEmail;
  age?: number;
  isActive: boolean;
}

// 使用泛型
function findItem<T>(
  items: T[],
  predicate: (item: T) => boolean
): T | undefined {
  return items.find(predicate);
}

// 使用联合类型和字面量类型
type Status = "pending" | "approved" | "rejected";
type Priority = "low" | "medium" | "high";

interface Task {
  id: number;
  title: string;
  status: Status;
  priority: Priority;
  assignee?: User;
}

// 使用映射类型
type PartialUser = Partial<User>;
type RequiredUser = Required<User>;
type PickUser = Pick<User, "id" | "name">;
type OmitUser = Omit<User, "age">;

// 条件类型
type NonNullableUser = NonNullable<User | null | undefined>;
type UserKeys = keyof User;

// 使用示例
const users: User[] = [
  { id: 1, name: "Alice", email: "alice@example.com", isActive: true },
  { id: 2, name: "Bob", email: "bob@example.com", age: 30, isActive: true },
  { id: 3, name: "Charlie", email: "charlie@example.com", isActive: false },
];

// 查找活跃用户
const activeUser = findItem(users, (user) => user.isActive);
console.log(activeUser);

// 类型守卫
function isActiveUser(user: User): user is User & { isActive: true } {
  return user.isActive;
}

const activeUsers = users.filter(isActiveUser);
console.log(activeUsers);

类型系统对比

特性PythonTypeScript
类型注解语法variable: typevariable: type
可选类型Optional[T]T | NoneT | undefinedT?
联合类型Union[T1, T2]T1 | T2T1 | T2
泛型Generic[T]<T>
接口Protocolinterface
类型别名TypeAliastype
类型检查器mypytsc
运行时检查无内置支持无内置支持

练习

  1. 为现有的 Python 函数添加类型注解

参考答案:

python
# Python
def add(a: int, b: int) -> int:
    return a + b
  1. 创建一个 TypeScript 接口定义用户管理系统

参考答案:

typescript
// TypeScript
interface User {
  id: number;
  name: string;
  email: string;
}
interface UserManager {
  addUser(user: User): void;
  getUser(id: number): User | undefined;
  removeUser(id: number): void;
}
  1. 使用泛型实现通用的数据结构

参考答案:

python
# Python (使用泛型)
from typing import TypeVar, Generic, List
T = TypeVar('T')
class Stack(Generic[T]):
    def __init__(self):
        self.items: List[T] = []
    def push(self, item: T):
        self.items.append(item)
    def pop(self) -> T:
        return self.items.pop()
stack = Stack[int]()
stack.push(1)
stack.push(2)
print(stack.pop())
typescript
// TypeScript
class Stack<T> {
  private items: T[] = [];
  push(item: T) {
    this.items.push(item);
  }
  pop(): T | undefined {
    return this.items.pop();
  }
}
const stack = new Stack<number>();
stack.push(1);
stack.push(2);
console.log(stack.pop());
  1. 配置 mypy 和 TypeScript 编译器

参考答案:

bash
# Python
pip install mypy
# 运行类型检查
mypy your_script.py

# TypeScript
npm install -g typescript
# 生成 tsconfig.json
npx tsc --init
# 编译 TypeScript
npx tsc your_script.ts
  1. 比较 Python 和 TypeScript 的类型系统差异

参考答案:

  • Python 类型注解是可选的,运行时不强制,主要用于静态检查。
  • TypeScript 类型是强制的,编译时检查,运行时会被擦除。
  • TypeScript 支持接口、泛型、联合类型、类型推断等,Python 也支持泛型但功能较弱。
  • TypeScript 更适合大型前端项目,Python 类型系统更灵活。

下一步

现在你已经了解了类型系统,接下来我们将学习综合案例。