Eliminating the Build Step: Running TypeScript Directly in Deno
Learn how Deno eliminates the TypeScript build step by integrating transpilation into the runtime, allowing for direct execution of .ts files with a security-first permission model.
27 Nov 2025, 13:48 UTC

The Friction of the Transpilation Loop
For years, the standard TypeScript workflow has required a middleman. You write .ts files, run a compiler like tsc or a bundler like Webpack to strip the types into .js, and then execute that JavaScript in a runtime. This "build step" introduces latency into the development loop and adds complexity to CI/CD pipelines, as you must manage two sets of files: the source and the distribution.
Deno removes this friction by treating TypeScript as a first-class citizen. Instead of requiring a separate build phase, Deno integrates the TypeScript compiler internally, allowing you to execute .ts files directly. The takeaway is simple: you can move from code change to execution in a single command, treating your type-annotated source as the actual runtime entry point.
How Deno Handles TypeScript Execution
Deno does not "convert" your code into a separate folder of JavaScript files. Instead, it handles the transpilation (the process of removing type annotations to make the code valid JavaScript) in memory. To mitigate the performance hit of compiling on every start, Deno uses a snapshotting mechanism and a cache for compiled modules.
This architectural choice changes how you manage dependencies. Rather than relying on a node_modules directory, Deno uses URL-based imports. When you import a TypeScript module via a URL, Deno downloads it, compiles it, and caches it locally. This ensures that type safety is maintained across your entire dependency graph without needing a centralized package manager to resolve versions before the code can run.
Practical Example: Direct Execution and Permissions
To see this in action, you don't need a package.json or a tsconfig.json to get started. You can write a typed script and run it immediately.
// server.ts
import { serve } from "https://deno.land/std@0.190.0/http/server.ts";
interface RequestData {
name: string;
}
serve((_req) => {
const data: RequestData = { name: "Deno User" };
return new Response(`Hello, ${data.name}!`);
});
To run this file, use the deno run command. Because Deno is secure by default, you must explicitly grant network access using the --allow-net flag. Run this in your terminal:
# Run from your local shell
# Permission: --allow-net is required to bind to a port
deno run --allow-net server.ts
Verification: If you omit the --allow-net flag, Deno will throw a PermissionDenied error and prompt you to grant access. This confirms that the security sandbox is active regardless of the language (JS or TS) being executed.
The Trade-off: Execution vs. Type Checking
It is critical to understand a key distinction in Deno's design: direct execution is not the same as type checking.
To keep startup times fast, the deno run command strips the types and executes the code without performing a full type-check of the logic. This means your code will run even if there are TypeScript errors in your source. This is a deliberate engineering trade-off to prioritize developer velocity over strictness during the execution phase.
To ensure your code is actually type-safe, you must run a separate check command:
# Run this to find type errors without executing the code
deno check server.ts
Compatibility and Limitations
While Deno simplifies the TS workflow, it differs from the Node.js ecosystem in two main ways:
- CommonJS: Deno uses ES Modules (ESM). If you need to use a legacy CommonJS library, you must use the
npm:specifier (e.g.,import lodash from "npm:lodash"), which tells Deno to handle the compatibility layer. - Tooling: Because there is no
node_modulesfolder by default, some IDEs may require the Deno extension to correctly resolve types from URLs.
Closing Action
If you are starting a new project and want to eliminate the overhead of build scripts, try migrating a single utility script to Deno. Replace your tsc & node chain with a single deno run command and integrate deno check into your CI pipeline to maintain type integrity.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.