类型系统
类型注解
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.0JavaScript 类型注解(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);类型系统对比
| 特性 | Python | TypeScript |
|---|---|---|
| 类型注解语法 | variable: type | variable: type |
| 可选类型 | Optional[T] 或 T | None | T | undefined 或 T? |
| 联合类型 | Union[T1, T2] 或 T1 | T2 | T1 | T2 |
| 泛型 | Generic[T] | <T> |
| 接口 | Protocol | interface |
| 类型别名 | TypeAlias | type |
| 类型检查器 | mypy | tsc |
| 运行时检查 | 无内置支持 | 无内置支持 |
练习
- 为现有的 Python 函数添加类型注解
参考答案:
python
# Python
def add(a: int, b: int) -> int:
return a + b- 创建一个 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;
}- 使用泛型实现通用的数据结构
参考答案:
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());- 配置 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- 比较 Python 和 TypeScript 的类型系统差异
参考答案:
- Python 类型注解是可选的,运行时不强制,主要用于静态检查。
- TypeScript 类型是强制的,编译时检查,运行时会被擦除。
- TypeScript 支持接口、泛型、联合类型、类型推断等,Python 也支持泛型但功能较弱。
- TypeScript 更适合大型前端项目,Python 类型系统更灵活。
下一步
现在你已经了解了类型系统,接下来我们将学习综合案例。