JSON 转换为 TypeScript:类型和接口指南
学习将 JSON 转换为 TypeScript 类型和接口。涵盖工具、最佳实践和 Zod 运行时验证。
Big JSON Team
• Technical WriterExpert in JSON data manipulation, API development, and web technologies. Passionate about creating tools that make developers' lives easier.
# JSON 转换为 TypeScript:类型和接口指南
将 JSON 数据转换为 TypeScript 类型是现代 Web 开发的关键实践。它提供编译时安全性、自动完成和更好的开发体验。
为什么将 JSON 转换为 TypeScript?
编译时安全
interface User {
id: number;
name: string;
}
const user: User = {
id: 1,
name: "张三"
// age: 30 ❌ 错误:'age' 不存在于类型 'User'
};
更好的自动完成
使用 TypeScript 类型,您的 IDE 可以:
- ✅ 显示可用字段
- ✅ 显示字段类型
- ✅ 检查拼写错误
- ✅ 提供重构工具
错误检测
const user: User = {
id: "123", // ❌ 类型错误:字符串而不是数字
name: "张三"
};
快速示例
JSON 数据
{
"id": 1,
"name": "张三",
"email": "zhang@example.com",
"active": true,
"roles": ["admin", "user"]
}
手动创建的 TypeScript 接口
interface User {
id: number;
name: string;
email: string;
active: boolean;
roles: string[];
}
// 使用
const user: User = JSON.parse(jsonString);
console.log(user.name); // ✓ 类型安全
JSON 到 TypeScript 类型映射
基本类型
| JSON 类型 | TypeScript 类型 |
|-----------|-----------------|
| 字符串 | string |
| 数字 | number |
| 布尔值 | boolean |
| null | null |
| 数组 | T[] 或 Array |
| 对象 | interface 或 type |
示例
// 简单类型
{
"name": "张三" // string
"age": 30, // number
"active": true, // boolean
"deleted": null, // null
}
// 数组
{
"tags": ["json", "typescript"] // string[]
"scores": [95, 87, 92] // number[]
"users": [{ ... }] // User[]
}
// 嵌套对象
{
"user": {
"id": 1,
"profile": {
"bio": "开发者"
}
}
}
处理可选和可空字段
可选字段(可能未定义)
interface User {
id: number;
name: string;
middleName?: string; // 可选:可能未定义
}
// 使用
const user: User = {
id: 1,
name: "张三"
// middleName 是可选的
};
可空字段(可能为 null)
interface User {
id: number;
name: string;
deletedAt: string | null; // 可空:可能为 null
}
// 使用
const user: User = {
id: 1,
name: "张三",
deletedAt: null // 或日期字符串
};
既可选又可空
interface User {
id: number;
name: string;
nickname?: string | null; // 既可选又可空
}
// 所有这些都有效
const user1: User = { id: 1, name: "张三" };
const user2: User = { id: 1, name: "张三", nickname: null };
const user3: User = { id: 1, name: "张三", nickname: "小张" };
数组和嵌套对象
简单数组
interface User {
id: number;
name: string;
tags: string[]; // 字符串数组
scores: number[]; // 数字数组
}
对象数组
interface Post {
id: number;
title: string;
}
interface User {
id: number;
name: string;
posts: Post[]; // Post 对象数组
}
嵌套对象
interface User {
id: number;
name: string;
profile: {
bio: string;
avatar: string;
location: {
city: string;
country: string;
};
};
}
更好的方式:分离接口
interface Location {
city: string;
country: string;
}
interface Profile {
bio: string;
avatar: string;
location: Location;
}
interface User {
id: number;
name: string;
profile: Profile;
}
在线工具:quicktype.io
最简单的转换方法
步骤:快速类型的特点
- ✅ 多种输出格式
- ✅ 自定义选项
- ✅ 实时预览
- ✅ 支持 Schema
配置选项
在生成之前自定义:
- 接口 vs 类型: 选择输出风格
- 可选属性: 处理缺失字段
- 运行时验证: 生成验证器
quicktype CLI
对于自动化和脚本化转换。
安装
npm install -g quicktype
基本用法
# 将 JSON 文件转换为 TypeScript
quicktype -o User.ts -l typescript data.json
# 从 URL 读取 JSON
quicktype -o User.ts -l typescript https://api.example.com/users
# 指定类型名
quicktype --type-name User -o User.ts data.json
# 生成接口而不是类型
quicktype --lang typescript --interface-name User data.json
批量转换
# 转换多个文件
for file in *.json; do
quicktype "$file" -o "${file%.json}.ts"
done
VS Code 扩展
Paste JSON as Code(QuickType)
安装:JSON Schema 与 TypeScript
从 Schema 生成类型
# 使用 json-schema-to-typescript
npm install -g json-schema-to-typescript
# 生成类型
json2ts schema.json > User.ts
优点
- ✅ 单一信息来源
- ✅ 可重用 Schema
- ✅ 运行时验证
处理特殊数据类型
日期
// 作为字符串(ISO 8601)
interface Post {
createdAt: string; // "2026-01-13T10:00:00Z"
}
// 更好:使用 Date
interface Post {
createdAt: Date;
}
// 解析时转换
const post = JSON.parse(jsonString);
post.createdAt = new Date(post.createdAt);
正则表达式
interface Config {
pattern: string; // 存储为字符串
}
// 使用时
const config: Config = JSON.parse(jsonString);
const regex = new RegExp(config.pattern);
区分联合类型
interface Cat {
type: "cat";
meow: string;
}
interface Dog {
type: "dog";
bark: string;
}
type Pet = Cat | Dog;
// 类型守卫
function describe(pet: Pet): string {
switch (pet.type) {
case "cat":
return pet.meow;
case "dog":
return pet.bark;
}
}
运行时验证
Zod
Zod 提供运行时验证和类型推断。
安装:npm install zod
定义 Schema:
import { z } from 'zod';
const UserSchema = z.object({
id: z.number(),
name: z.string(),
email: z.string().email(),
active: z.boolean(),
middleName: z.string().optional()
});
// 自动生成类型
type User = z.infer<typeof UserSchema>;
验证数据:
const data = JSON.parse(jsonString);
try {
const user: User = UserSchema.parse(data);
console.log("✓ 有效用户");
} catch (error) {
console.log("✗ 无效数据:", error.errors);
}
Pydantic(Python)
from pydantic import BaseModel
from typing import Optional
class User(BaseModel):
id: int
name: str
email: str
active: bool
middle_name: Optional[str] = None
# 从 JSON 解析
user = User.parse_raw(json_string)
# 验证和转换
print(user.name) # 类型安全
处理 API 响应
常见 API 响应结构
interface ApiResponse<T> {
success: boolean;
data: T;
error?: string;
timestamp: string;
}
interface User {
id: number;
name: string;
}
// 使用泛型
const response: ApiResponse<User[]> = JSON.parse(apiJson);
if (response.success) {
response.data.forEach(user => {
console.log(user.name);
});
}
分页
interface PaginatedResponse<T> {
data: T[];
pagination: {
page: number;
limit: number;
total: number;
hasMore: boolean;
};
}
const response: PaginatedResponse<User> = JSON.parse(json);
最佳实践
1. 从准确开始,然后精化
// ✗ 太宽泛
interface User {
[key: string]: any;
}
// ✓ 准确
interface User {
id: number;
name: string;
email: string;
}
2. 使用工具生成,然后自定义
// 使用 quicktype 生成,然后:
// - 添加方法
// - 改进字段名
// - 添加注释
interface User {
id: number;
name: string;
// 自定义方法
getDisplayName(): string {
return this.name.toUpperCase();
}
}
3. 组织相关类型
// user-types.ts
export interface User {
id: number;
name: string;
profile: Profile;
}
export interface Profile {
bio: string;
avatar: string;
}
// 在应用中使用
import { User, Profile } from './user-types';
4. 分离业务逻辑
// types.ts - 从 API 的原始数据
interface ApiUser {
id: number;
firstName: string;
lastName: string;
}
// domain.ts - 业务逻辑
interface User extends ApiUser {
fullName: string;
}
// 转换函数
function toUser(apiUser: ApiUser): User {
return {
...apiUser,
fullName: ${apiUser.firstName} ${apiUser.lastName}
};
}
工具比较
| 工具 | 速度 | 自定义 | 最佳用途 |
|------|------|--------|---------|
| quicktype.io | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | 快速转换 |
| VS Code 扩展 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | 集成工作流 |
| Zod | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | 运行时验证 |
| 手动编写 | ⭐⭐ | ⭐⭐⭐⭐⭐ | 完全控制 |
常见模式
可区分联合
type Result<T> =
| { status: 'success'; data: T }
| { status: 'error'; error: string };
const result: Result<User> = JSON.parse(json);
if (result.status === 'success') {
console.log(result.data.name);
}
可选属性的缺省值
interface Config {
port?: number;
host?: string;
}
const config: Config = {
port: 3000,
host: 'localhost'
};
const port = config.port ?? 8000; // 缺省值
故障排除
问题:任何类型太宽泛
// ✗ 避免
const user: any = JSON.parse(json);
// ✓ 正确
const user: User = JSON.parse(json);
问题:缺少字段类型
使用 quicktype 或手动指定所有字段。
问题:API 返回不一致的数据
使用 Zod 进行运行时验证和转换。
结论
将 JSON 转换为 TypeScript 类型是现代 Web 开发的关键:
- 工具(quicktype): 快速开始
- 运行时验证(Zod): 确保数据安全
- 类型精化: 维护代码质量
- 最佳实践: 组织和可重用
选择适合您的方法,保持类型安全!