Overview
Deno has first-class TypeScript support built into the runtime. You can run TypeScript files directly without any build step, configuration files, or additional tooling.
Deno compiles TypeScript to JavaScript on the fly, caching the compiled output for fast subsequent runs.
Zero Configuration
Unlike traditional TypeScript setups, Deno requires:
❌ No tsconfig.json
❌ No package.json
❌ No build tools
❌ No transpiler configuration
✅ Just run .ts files directly
# Create a TypeScript file
echo 'console.log("Hello" as string);' > hello.ts
# Run it immediately
deno run hello.ts
How It Works
From the Deno source code (cli/tsc/README.md), the TypeScript compilation process:
Compilation Pipeline
Parse : Read and parse TypeScript source
Type Check : Validate types (if enabled)
Emit : Transform to JavaScript
Cache : Store compiled output
Execute : Run in V8 engine
Type Checking Modes
Deno offers flexible type checking:
Full Type Checking
# Type check before running (default in Deno 2.0+)
deno run script.ts
# Explicit type checking
deno check script.ts
Skip Type Checking
For faster iteration during development:
# Skip type checking, only transform syntax
deno run --no-check script.ts
Check Remote Code
# Type check including remote dependencies
deno check --remote script.ts
TypeScript Configuration
While not required, you can customize TypeScript behavior:
{
"compilerOptions" : {
"strict" : true ,
"noImplicitAny" : true ,
"strictNullChecks" : true ,
"noUnusedLocals" : true ,
"noUnusedParameters" : true
}
}
Deno automatically sets sensible defaults. You only need to configure options when overriding defaults.
Supported TypeScript Features
Deno supports modern TypeScript out of the box:
Type Annotations
function greet ( name : string ) : string {
return `Hello, ${ name } !` ;
}
const count : number = 42 ;
const items : Array < string > = [ "a" , "b" , "c" ];
Interfaces and Types
interface User {
id : number ;
name : string ;
email ?: string ;
}
type Result < T > =
| { success : true ; data : T }
| { success : false ; error : string };
function getUser ( id : number ) : Result < User > {
// ...
}
Generics
function identity < T >( arg : T ) : T {
return arg ;
}
class Container < T > {
constructor ( private value : T ) {}
getValue () : T {
return this . value ;
}
}
Enums
enum Direction {
North ,
South ,
East ,
West ,
}
const dir : Direction = Direction . North ;
Decorators
Experimental decorators are supported:
function logged ( target : any , propertyKey : string , descriptor : PropertyDescriptor ) {
const original = descriptor . value ;
descriptor . value = function ( ... args : any []) {
console . log ( `Calling ${ propertyKey } ` );
return original . apply ( this , args );
};
}
class Service {
@ logged
process ( data : string ) {
return data . toUpperCase ();
}
}
Namespace Support
namespace Utils {
export function format ( value : number ) : string {
return value . toFixed ( 2 );
}
}
Utils . format ( 3.14159 );
Type Definitions
Built-in Types
Deno provides comprehensive type definitions:
// Deno namespace types are built-in
const file : Deno . FsFile = await Deno . open ( "file.txt" );
const info : Deno . FileInfo = await Deno . stat ( "file.txt" );
// Web standard APIs
const response : Response = await fetch ( "https://deno.land" );
const encoder : TextEncoder = new TextEncoder ();
Library References
From the source code, Deno provides different type libraries:
/// < reference lib = "deno.window" />
// For main runtime (default)
/// < reference lib = "deno.worker" />
// For web workers
/// < reference lib = "deno.ns" />
// Core Deno namespace
Third-Party Types
// Types come with JSR packages
import { assertEquals } from "jsr:@std/assert" ;
// npm packages with @types
import express from "npm:express" ;
import type { Request } from "npm:@types/express" ;
// Inline type declarations
import type { User } from "https://example.com/types.ts" ;
Type-Only Imports
Import types without runtime cost:
// Import only types
import type { User , Post } from "./types.ts" ;
// Mixed import
import { database , type Config } from "./database.ts" ;
// Type-only export
export type { User , Post };
export { createUser };
JSX/TSX Support
Deno supports JSX and TSX out of the box:
import { h } from "preact" ;
interface Props {
name : string ;
age : number ;
}
export function Greeting ({ name , age } : Props ) {
return (
< div >
< h1 > Hello, { name } ! </ h1 >
< p > Age: { age } </ p >
</ div >
);
}
Declaration Files
Generating Declarations
# Generate .d.ts files
deno run --emit=declarations script.ts
Using Declaration Files
// types.d.ts
declare module "my-module" {
export function doSomething () : void ;
}
// main.ts
import { doSomething } from "my-module" ;
Ambient Declarations
// global.d.ts
declare global {
interface Window {
myCustomProperty : string ;
}
}
// Now available globally
window . myCustomProperty = "value" ;
TypeScript Compiler Integration
From cli/tsc/README.md, Deno uses:
Microsoft TypeScript : Full TypeScript compiler
typescript-go : Experimental Go-based compiler (faster)
Custom integration : Runtime-specific optimizations
// Deno's TypeScript integration provides:
// - Custom module resolution
// - Multiple library contexts (window/worker)
// - Node.js compatibility layer
// - Special handling for global symbols
Fast Refresh with —watch
Automatic recompilation on file changes:
# Watch mode
deno run --watch script.ts
# Watch with type checking
deno run --watch --check script.ts
When a file changes:
Deno detects the modification
Invalidates affected cache
Recompiles changed files
Restarts the program
Incremental Compilation
Deno caches compiled outputs:
$DENO_DIR/gen/
file/
home/user/project/
script.ts.js # Compiled JavaScript
script.ts.meta # Type information
script.ts.buildinfo # Incremental state
Code Cache
V8 code cache for faster subsequent runs:
// First run: ~200ms (compile + execute)
// Second run: ~20ms (cache hit)
Skip Type Checking in Development
# Fast iteration
deno run --no-check script.ts
# Production deployment
deno check script.ts && deno run script.ts
Common Patterns
interface Config {
port : number ;
host : string ;
debug : boolean ;
}
const config : Config = {
port: 8000 ,
host: "localhost" ,
debug: true ,
};
// Deno enables strict null checks by default
function findUser ( id : number ) : User | undefined {
return users . find ( u => u . id === id );
}
const user = findUser ( 1 );
// TypeScript error: Object possibly undefined
console . log ( user . name );
// Correct
if ( user ) {
console . log ( user . name );
}
interface Cat {
meow () : void ;
}
interface Dog {
bark () : void ;
}
function isCat ( animal : Cat | Dog ) : animal is Cat {
return 'meow' in animal ;
}
function handlePet ( pet : Cat | Dog ) {
if ( isCat ( pet )) {
pet . meow (); // TypeScript knows it's a Cat
} else {
pet . bark (); // TypeScript knows it's a Dog
}
}
interface User {
id : number ;
name : string ;
email : string ;
role : string ;
}
// Pick specific fields
type UserPreview = Pick < User , "id" | "name" >;
// Omit fields
type UserWithoutId = Omit < User , "id" >;
// Make all fields optional
type PartialUser = Partial < User >;
// Make all fields required
type RequiredUser = Required < PartialUser >;
// Make all fields readonly
type ImmutableUser = Readonly < User >;
Troubleshooting
If you encounter type errors, try: # Clear the cache
deno cache --reload script.ts
# Explicit type checking
deno check --all script.ts
Common Issues
// Issue: Implicit any
function process ( data ) { // ❌ Parameter 'data' implicitly has 'any' type
return data . value ;
}
// Solution: Add type annotation
function process ( data : { value : string }) { // ✅
return data . value ;
}
Migration from Node.js
Key differences when migrating TypeScript from Node.js:
No tsconfig.json Deno uses sensible defaults, no config file needed
No node_modules Direct URL imports instead of npm packages
File extensions required Always use .ts extension in imports
Strict mode by default All strict TypeScript options enabled
Next Steps Learn about Module System to understand how TypeScript modules are loaded and resolved.