Modern TypeScript patterns and migration guidance for Deno: resource management with 'using', async generators, error handling, and Web Standard APIs. Use when migrating from Node.js, implementing cleanup logic, or learning modern JS/TS patterns.
View on GitHubjahanson/cc-plugins
deno-lsp
deno-lsp/skills/deno-patterns/SKILL.md
January 21, 2026
Select agents to install to:
npx add-skill https://github.com/jahanson/cc-plugins/blob/main/deno-lsp/skills/deno-patterns/SKILL.md -a claude-code --skill deno-patternsInstallation paths:
.claude/skills/deno-patterns/# Deno Modern Patterns & Migration
## When to Use This Skill
Use this skill when:
- Migrating from Node.js to Deno
- Learning modern JavaScript/TypeScript patterns
- Implementing resource management
- Working with timers, polling, or cleanup logic
- Handling errors in Deno
- Choosing between old and new patterns
**Note:** Always read `deno-core.md` first for essential configuration and practices.
---
## Resource Management with `using`
### The Problem with Manual Cleanup
**Old Pattern:**
```javascript
// Manual timer cleanup - error-prone
const id = setInterval(() => {
console.log("Tick!");
}, 1000);
// Later, cleanup (easy to forget!)
clearInterval(id);
```
**Problems:**
- Resource leaks if cleanup is missed
- Not exception-safe
- Resource not tied to lexical scope
- Cleanup code separated from acquisition
### The `using` Statement (Deno >= v2.4)
**New Pattern:**
```typescript
// Automatic, exception-safe cleanup
class Timer {
#handle: number;
constructor(cb: () => void, ms: number) {
this.#handle = setInterval(cb, ms);
}
[Symbol.dispose]() {
clearInterval(this.#handle);
console.log("Timer disposed");
}
}
using timer = new Timer(() => {
console.log("Tick!");
}, 1000);
// Timer automatically cleaned up at end of scope
```
**Benefits:**
- Automatic cleanup at scope exit
- Exception-safe (cleanup happens even if errors occur)
- Follows RAII (Resource Acquisition Is Initialization) principles
- Prevents resource leaks in complex control flows
- Composable with multiple `using` declarations
### Async Resource Management
For async cleanup, use `await using` with `Symbol.asyncDispose`:
```typescript
class DatabaseConnection {
#conn: Connection;
constructor(conn: Connection) {
this.#conn = conn;
}
async [Symbol.asyncDispose]() {
await this.#conn.close();
console.log("Database connection closed");
}
}
// Automatically closes when scope exits
await using db = new DatabaseConnection(conn);
await db.query("