| name | deno-typescript |
| description | Guidelines for developing with Deno and TypeScript using modern runtime features, security model, and native tooling |
Deno TypeScript Development
You are an expert in Deno and TypeScript development with deep knowledge of building secure, modern applications using Deno's native TypeScript support and built-in tooling.
TypeScript General Guidelines
Basic Principles
- Use English for all code and documentation
- Always declare types for variables and functions (parameters and return values)
- Avoid using
any type - create necessary types instead
- Use JSDoc to document public classes and methods
- Write concise, maintainable, and technically accurate code
- Use functional and declarative programming patterns
- No configuration needed - Deno runs TypeScript natively
Nomenclature
- Use PascalCase for classes, types, and interfaces
- Use camelCase for variables, functions, and methods
- Use kebab-case for file and directory names
- Use UPPERCASE for environment variables
- Use descriptive variable names with auxiliary verbs:
isLoading, hasError, canDelete
- Start each function with a verb
Functions
- Write short functions with a single purpose
- Use arrow functions for simple operations
- Use async/await for asynchronous operations
- Prefer the RO-RO pattern for multiple parameters
Types and Interfaces
- Prefer interfaces over types for object shapes
- Avoid enums; use const objects with
as const
- Use Zod for runtime validation with inferred types
- Use
readonly for immutable properties
Deno-Specific Guidelines
Project Structure
src/
routes/
{resource}/
mod.ts
handlers.ts
validators.ts
middleware/
auth.ts
logger.ts
services/
{domain}_service.ts
types/
mod.ts
utils/
mod.ts
deps.ts
main.ts
deno.json
Module System
- Use ES modules with explicit file extensions
- Use
deps.ts pattern for centralized dependency management
- Import from URLs or use import maps in
deno.json
- Use JSR (jsr.io) for Deno-native packages
export { serve } from "https://deno.land/std@0.208.0/http/server.ts";
export { z } from "https://deno.land/x/zod@v3.22.4/mod.ts";
{
"imports": {
"std/": "https://deno.land/std@0.208.0/",
"hono": "https://deno.land/x/hono@v3.11.7/mod.ts"
}
}
Security Model
Deno is secure by default. Request only necessary permissions:
deno run --allow-net --allow-read=./data --allow-env main.ts
--allow-net=example.com
--allow-read=./path
--allow-write=./path
--allow-env=API_KEY
--allow-run=cmd
const status = await Deno.permissions.request({ name: 'net', host: 'api.example.com' })
if (status.state === 'granted') {
}
HTTP Server with Deno.serve
Deno.serve({ port: 8000 }, (req) => {
const url = new URL(req.url)
if (url.pathname === '/api/users' && req.method === 'GET') {
return Response.json({ users: [] })
}
return new Response('Not Found', { status: 404 })
})
Using Hono with Deno
import { Hono } from 'https://deno.land/x/hono/mod.ts'
const app = new Hono()
app.get('/', (c) => c.text('Hello Deno!'))
app.get('/api/users', (c) => c.json({ users: [] }))
Deno.serve(app.fetch)
Using Fresh Framework
import { PageProps } from "$fresh/server.ts";
export default function Home(props: PageProps) {
return (
<div>
<h1>Welcome to Fresh</h1>
</div>
);
}
import { Handlers } from "$fresh/server.ts";
export const handler: Handlers = {
async GET(_req, _ctx) {
const users = await getUsers();
return Response.json(users);
},
};
Database Integration
const kv = await Deno.openKv()
await kv.set(['users', '1'], { name: 'John', email: 'john@example.com' })
const result = await kv.get(['users', '1'])
console.log(result.value)
const entries = kv.list({ prefix: ['users'] })
for await (const entry of entries) {
console.log(entry.key, entry.value)
}
Environment Variables
const apiKey = Deno.env.get('API_KEY')
import { load } from 'https://deno.land/std/dotenv/mod.ts'
const env = await load()
Testing with Built-in Test Runner
import { assertEquals, assertRejects } from 'https://deno.land/std/assert/mod.ts'
import { describe, it, beforeEach } from 'https://deno.land/std/testing/bdd.ts'
import { getUser, createUser } from './user_service.ts'
describe('User Service', () => {
beforeEach(() => {
})
it('should create a user', async () => {
const user = await createUser({ name: 'John', email: 'john@example.com' })
assertEquals(user.name, 'John')
})
it('should throw for invalid email', async () => {
await assertRejects(
() => createUser({ name: 'John', email: 'invalid' }),
Error,
'Invalid email'
)
})
})
Built-in Tooling
deno fmt
deno lint
deno check main.ts
deno bundle main.ts bundle.js
deno compile --allow-net main.ts
deno doc main.ts
deno info main.ts
Configuration with deno.json
{
"tasks": {
"dev": "deno run --watch --allow-net --allow-env main.ts",
"start": "deno run --allow-net --allow-env main.ts",
"test": "deno test --allow-net",
"lint": "deno lint",
"fmt": "deno fmt"
},
"imports": {
"std/": "https://deno.land/std@0.208.0/",
"@/": "./src/"
},
"compilerOptions": {
"strict": true,
"lib": ["deno.window"]
},
"lint": {
"rules": {
"tags": ["recommended"]
}
},
"fmt": {
"indentWidth": 2,
"singleQuote": true
}
}
Error Handling
class AppError extends Error {
constructor(
message: string,
public statusCode: number = 500,
public code: string = 'INTERNAL_ERROR'
) {
super(message)
this.name = 'AppError'
}
}
const handleRequest = async (req: Request): Promise<Response> => {
try {
return await processRequest(req)
} catch (error) {
if (error instanceof AppError) {
return Response.json({ error: error.message, code: error.code }, { status: error.statusCode })
}
console.error(error)
return Response.json({ error: 'Internal Server Error' }, { status: 500 })
}
}
Web Standards
Deno embraces web standards. Use:
fetch() for HTTP requests
Request and Response objects
URL and URLSearchParams
Web Crypto API for cryptography
Streams API for data streaming
FormData for multipart data
Performance
- Use web streams for large data processing
- Leverage Deno KV for fast key-value storage
- Use
Deno.serve for high-performance HTTP
- Compile to standalone executables for deployment