Deno has native TypeScript support, which is one of its most attractive features. Unlike Node.js, which requires configuring a TypeScript compiler, Deno can run TypeScript files directly without any additional transpilation steps.
TypeScript Support Overview
Deno includes a built-in TypeScript compiler, using V8 engine's TypeScript support and the swc compiler to provide fast type checking and transpilation.
Running TypeScript Directly
1. Basic Usage
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);
Run:
bashdeno run app.ts
2. Type Checking
Deno performs type checking at runtime:
bash# Type check at runtime deno run app.ts # Type check only (don't execute) deno check app.ts # Type check all files deno check **/*.ts
Type Definitions
1. Using Deno Built-in Types
Deno provides rich built-in type definitions:
typescript// File system operations const content: string = await Deno.readTextFile("./data.txt"); // HTTP server 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. Third-party Library Types
Modules imported from URLs usually include type definitions:
typescriptimport { Application, Router } from "https://deno.land/x/oak@v12.6.1/mod.ts"; const app = new Application(); const router = new Router();
3. Custom Type Definitions
If a module doesn't have type definitions, you can create custom types:
typescript// types.d.ts declare module "https://example.com/module.js" { export function doSomething(): void; export const value: number; }
Configuration Options
1. tsconfig.json
Deno supports using tsconfig.json for configuration:
json{ "compilerOptions": { "strict": true, "esModuleInterop": true, "skipLibCheck": true }, "include": ["src/**/*"], "exclude": ["node_modules"] }
2. Command Line Options
bash# Disable type checking (not recommended) deno run --no-check app.ts # Use specific tsconfig deno run --config=tsconfig.json app.ts # Enable strict mode deno run app.ts # Strict mode enabled by default
Type Checking Strategies
1. Local Type Checking
bash# Check local files deno check app.ts # Check entire project deno check src/**/*.ts
2. Remote Type Checking
Deno caches type definitions for remote modules:
bash# Re-download and check remote types deno check --remote app.ts # Clear type cache deno cache --reload app.ts
Practical Application Examples
1. Type-safe API Server
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. Type-safe Database Operations
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. Type-safe Utility Functions
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; } }
Type Checking Performance Optimization
1. Incremental Type Checking
Deno caches type checking results:
bash# First run performs full type check deno run app.ts # Subsequent runs use cache deno run app.ts
2. Selective Type Checking
bash# Only check modified files deno check app.ts # Exclude certain files deno check --exclude=**/*.test.ts src/**/*.ts
Comparison with Node.js
| Feature | Deno | Node.js |
|---|---|---|
| TypeScript Support | Native support | Requires tsc configuration |
| Execution Method | Run .ts files directly | Need to compile to .js first |
| Type Checking | Runtime checking | Compile-time checking |
| Configuration Complexity | Zero configuration | Requires tsconfig.json |
| Performance | Fast compilation with swc | Slower with tsc |
| Type Definitions | Auto-loaded | Requires @types packages |
Best Practices
- Always use types: Take full advantage of TypeScript's type system
- Enable strict mode: Use
strict: truefor better type safety - Use interfaces for data structures: Clearly define API and data model types
- Avoid any type: Use unknown or specific types instead
- Run type checks regularly: Use
deno checkto ensure code quality - Leverage generics: Write reusable type-safe code
Deno's TypeScript support allows developers to enjoy the benefits of type safety without complex configuration and build processes, greatly improving development efficiency and code quality.