乐闻世界logo
搜索文章和话题

Deno 如何支持 TypeScript?

2月21日 16:10

Deno 原生支持 TypeScript,这是其最吸引人的特性之一。与 Node.js 需要配置 TypeScript 编译器不同,Deno 可以直接运行 TypeScript 文件,无需任何额外的转译步骤。

TypeScript 支持概述

Deno 内置了 TypeScript 编译器,使用 V8 引擎的 TypeScript 支持和 swc 编译器来提供快速的类型检查和转译。

直接运行 TypeScript

1. 基本用法

typescript
// app.ts interface User { id: number; name: string; email: string; } function createUser(user: User): User { console.log(`Creating user: ${user.name}`); return user; } const newUser: User = { id: 1, name: "John Doe", email: "john@example.com" }; createUser(newUser);

运行:

bash
deno run app.ts

2. 类型检查

Deno 会在运行时进行类型检查:

bash
# 运行时进行类型检查 deno run app.ts # 仅类型检查(不执行) deno check app.ts # 类型检查所有文件 deno check **/*.ts

类型定义

1. 使用 Deno 内置类型

Deno 提供了丰富的内置类型定义:

typescript
// 文件系统操作 const content: string = await Deno.readTextFile("./data.txt"); // HTTP 服务器 import { serve } from "https://deno.land/std@0.208.0/http/server.ts"; const handler = async (req: Request): Promise<Response> => { return new Response("Hello World"); };

2. 第三方库类型

从 URL 导入的模块通常包含类型定义:

typescript
import { Application, Router } from "https://deno.land/x/oak@v12.6.1/mod.ts"; const app = new Application(); const router = new Router();

3. 自定义类型定义

如果模块没有类型定义,可以创建自定义类型:

typescript
// types.d.ts declare module "https://example.com/module.js" { export function doSomething(): void; export const value: number; }

配置选项

1. tsconfig.json

Deno 支持使用 tsconfig.json 进行配置:

json
{ "compilerOptions": { "strict": true, "esModuleInterop": true, "skipLibCheck": true }, "include": ["src/**/*"], "exclude": ["node_modules"] }

2. 命令行选项

bash
# 禁用类型检查(不推荐) deno run --no-check app.ts # 使用特定的 tsconfig deno run --config=tsconfig.json app.ts # 启用严格模式 deno run app.ts # 默认启用严格模式

类型检查策略

1. 本地类型检查

bash
# 检查本地文件 deno check app.ts # 检查整个项目 deno check src/**/*.ts

2. 远程类型检查

Deno 会缓存远程模块的类型定义:

bash
# 重新下载并检查远程类型 deno check --remote app.ts # 清除类型缓存 deno cache --reload app.ts

实际应用示例

1. 类型安全的 API 服务器

typescript
// api-server.ts interface User { id: number; name: string; email: string; } interface CreateUserRequest { name: string; email: string; } const users: Map<number, User> = new Map(); function createUser(request: CreateUserRequest): User { const id = users.size + 1; const user: User = { id, ...request }; users.set(id, user); return user; } import { serve } from "https://deno.land/std@0.208.0/http/server.ts"; const handler = async (req: Request): Promise<Response> => { const url = new URL(req.url); if (req.method === "POST" && url.pathname === "/users") { try { const body: CreateUserRequest = await req.json(); const user = createUser(body); return new Response(JSON.stringify(user), { headers: { "Content-Type": "application/json" } }); } catch (error) { return new Response("Invalid request", { status: 400 }); } } return new Response("Not Found", { status: 404 }); }; await serve(handler, { port: 8000 });

2. 类型安全的数据库操作

typescript
// database.ts interface DatabaseRecord { id: string; createdAt: Date; updatedAt: Date; } interface Post extends DatabaseRecord { title: string; content: string; authorId: string; } class Database<T extends DatabaseRecord> { private records: Map<string, T> = new Map(); async create(record: Omit<T, keyof DatabaseRecord>): Promise<T> { const id = crypto.randomUUID(); const now = new Date(); const newRecord: T = { id, createdAt: now, updatedAt: now, ...record } as T; this.records.set(id, newRecord); return newRecord; } async findById(id: string): Promise<T | undefined> { return this.records.get(id); } } const postDB = new Database<Post(); const newPost = await postDB.create({ title: "Hello Deno", content: "TypeScript support is amazing!", authorId: "user-1" });

3. 类型安全的工具函数

typescript
// utils.ts type AsyncFunction<T = any> = (...args: any[]) => Promise<T>; async function retry<T>( fn: AsyncFunction<T>, maxAttempts: number = 3, delay: number = 1000 ): Promise<T> { let lastError: Error | undefined; for (let attempt = 1; attempt <= maxAttempts; attempt++) { try { return await fn(); } catch (error) { lastError = error as Error; if (attempt < maxAttempts) { await new Promise(resolve => setTimeout(resolve, delay)); } } } throw lastError; } async function fetchWithTimeout( url: string, timeout: number = 5000 ): Promise<Response> { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), timeout); try { const response = await fetch(url, { signal: controller.signal }); clearTimeout(timeoutId); return response; } catch (error) { clearTimeout(timeoutId); throw error; } }

类型检查性能优化

1. 增量类型检查

Deno 会缓存类型检查结果:

bash
# 首次运行会进行完整类型检查 deno run app.ts # 后续运行会使用缓存 deno run app.ts

2. 选择性类型检查

bash
# 只检查修改的文件 deno check app.ts # 排除某些文件 deno check --exclude=**/*.test.ts src/**/*.ts

与 Node.js 的对比

特性DenoNode.js
TypeScript 支持原生支持需要配置 tsc
运行方式直接运行 .ts 文件需要先编译为 .js
类型检查运行时检查编译时检查
配置复杂度零配置需要 tsconfig.json
性能使用 swc 快速编译使用 tsc 较慢
类型定义自动加载需要 @types 包

最佳实践

  1. 始终使用类型:充分利用 TypeScript 的类型系统
  2. 启用严格模式:使用 strict: true 获得更好的类型安全
  3. 使用接口定义数据结构:明确 API 和数据模型的类型
  4. 避免 any 类型:使用 unknown 或具体类型替代
  5. 定期运行类型检查:使用 deno check 确保代码质量
  6. 利用泛型:编写可复用的类型安全代码

Deno 的 TypeScript 支持使得开发者能够享受类型安全的好处,而无需复杂的配置和构建流程,大大提高了开发效率和代码质量。

标签:TypeScriptDeno