new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Deno · Fundamentals · all subjects

modules and imports

49 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

CSSStyleSheet implementation details

Deno implements a small slice of the CSSStyleSheet interface: cssRules returns the sheet's top-level rules as a frozen array (not a live CSSRuleList), creating a fresh array on each access; CSSRule.cssText returns the verbatim text of one top-level rule; replace(text) and replaceSync(text) swap the sheet's contents, with top-level @import rules dropped; new CSSStyleSheet() constructor is available but does not support the options argument (media, disabled, baseURL). Because Deno has no DOM, insertRule and deleteRule are not implemented.

CommonJS support in Deno

Deno runs Node's CommonJS modules (require and module.exports), so existing npm packages and Node projects work without conversion. The two systems are fully supported and interoperate, but ECMAScript modules are recommended for new code.

File extension determines module system

Deno decides which module system a file uses from its extension and the nearest package.json. A .mjs file is always an ES module, a .cjs file is always CommonJS, and .js and .ts files are treated as ES modules unless a package.json sets "type": "commonjs".

Local import specifiers must include full file extension

With ECMAScript modules, local import specifiers must always include the full file extension. The file extension cannot be omitted. For example, use import { add } from "./calc.ts" instead of import { add } from "./calc".

Dynamic import function

The import() function loads a module on demand and returns a promise for the module's namespace. Because import() runs at runtime, the specifier can be computed and the module is only fetched and evaluated when the call executes. This is useful for loading code conditionally or keeping rarely used features out of the startup path.

Dynamic import permissions

A dynamic import() whose specifier is a string literal is part of the static module graph and loads without extra permissions. One whose specifier is computed at runtime is checked against the permission system: local paths need --allow-read and remote URLs need --allow-import.

import.meta properties

Inside any module, import.meta exposes information about the current module. import.meta.url contains the module's URL (e.g., file:///path/to/main.ts), import.meta.main is true if this is the entry module, import.meta.filename contains the local file path (undefined for remote modules), import.meta.dirname contains the directory path (undefined for remote modules), and import.meta.resolve() resolves a specifier to a URL.

Using import.meta.main for dual-purpose modules

import.meta.main is commonly used to make a file work both as an entry point and as an importable library. Check if (import.meta.main) to run code only when the module is executed directly, not when imported by other code.

JSON import with type attribute

Deno supports importing JSON files using the with { type: "json" } import attribute syntax. Example: import data from "./data.json" with { type: "json" }; The imported data is accessible as an object.

Text file imports

Starting with Deno 2.4, text files can be imported using the with { type: "text" } import attribute. The import evaluates to a string. This is stable in Deno 2.8 and no longer requires a flag.

Bytes import with type attribute

Bytes can be imported using the with { type: "bytes" } import attribute, which evaluates to a Uint8Array. This feature is still experimental and requires the --unstable-raw-imports CLI flag or the unstable.raw-import option in deno.json.

CSS stylesheet imports

A stylesheet can be imported with with { type: "css" }, evaluating to a CSSStyleSheet object matching what browsers ship. This is useful for running unmodified browser module graphs in Deno, such as server-side rendering or testing web components. This feature is still experimental and requires the --unstable-raw-imports CLI flag or the unstable.raw-import option in deno.json.

ECMAScript modules as primary module system

Deno uses ECMAScript modules as its primary module system. Code is shared between files with standard import and export statements and runs directly without a bundler or build step. This is the same module system browsers use, keeping code portable across environments.

Dynamic imports with import attributes

Dynamic imports work with import attributes using the same syntax as static imports. Example: const { default: sheet } = await import("./styles.css", { with: { type: "css" } });

Import attribute permission requirements

Static imports and dynamic imports with a statically analyzable specifier are loaded as part of the module graph and require no permission. Only a dynamic import whose specifier cannot be analyzed (such as import(base + "styles.css")) reads the file at runtime and requires read permission (--allow-read).

Deferred module evaluation with import defer

Starting in Deno 2.8, the TC39 Deferred Module Evaluation proposal is supported. The import defer syntax loads a module and its dependencies but does not execute its top-level code until a property is read from the namespace. This defers the cost of modules that are only needed conditionally. The syntax is considered experimental and may change. Example: import defer * as expensive from "./expensive.ts"; console.log(expensive.value); triggers synchronous evaluation.

WebAssembly module imports

Deno supports importing Wasm modules directly. The named exports mirror the Wasm module's exports: functions, memories, and tables come through as their JavaScript objects, and a global export resolves to the value it holds rather than the WebAssembly.Global wrapper, matching the WebAssembly ES module integration.

Data URL imports

Deno supports importing data URLs, allowing import of content that isn't in a separate file. The data URL format is: data:[<media type>][;base64],<data>. For JavaScript modules, use application/javascript as the media type; TypeScript is also supported with application/typescript. This is useful for testing modules in isolation and creating mock modules during tests.

Data URL import examples

Example static import: import * as module from "data:application/javascript;base64,ZXhwb3J0IGNvbnN0IG1lc3NhZ2UgPSBcIkhlbGxvIGZyb20gZGF0YSBVUkxcIjs"; Example dynamic import: const plainModule = await import("data:application/javascript,export function greet() { return 'Hi there!'; }"); const textModule = await import("data:text/plain,export default 'This is plain text'");

Third-party module imports from registries

When working with third-party modules in Deno, use the same import syntax as for local code. Third-party modules are typically imported from a remote registry and start with jsr: or npm:. Example: import { camelCase } from "jsr:@luca/cases@1.0.0"; import { say } from "npm:cowsay@1.6.0";

Import map in deno.json

The imports field in deno.json is called the import map. It centralizes management of remote modules to avoid typing full version specifiers in multiple files. Example: { "imports": { "@luca/cases": "jsr:@luca/cases@^1.0.0", "cowsay": "npm:cowsay@^1.6.0" } }. With remapped specifiers, imports become cleaner: import { camelCase } from "@luca/cases";

Import map with --import-map option requires trailing slash entries

The Import Maps Standard requires two entries for each module: one for the module specifier and another with a trailing /. When using the --import-map import_map.json option, the import_map.json file must include both entries. Example: { "imports": { "@std/async": "jsr:@std/async@^1.0.0", "@std/async/": "jsr:/@std/async@^1.0.0/" } }. An import_map.json referenced by the importMap field in deno.json has the same requirements.

deno.json imports field extends import maps standard

The imports field in deno.json extends the import maps standard. When using the imports field directly in deno.json, you only need to specify the module specifier without the trailing /. Example: { "imports": { "@std/async": "jsr:@std/async@^1.0.0" } }.

Remapped specifier flexibility

In deno.json import maps, the remapped name can be any valid specifier. This is a powerful feature that can remap anything.

deno outdated command

The deno outdated command lists dependencies with newer versions available. Running deno outdated --update bumps versions in deno.json automatically.

deno bump-version command

The deno bump-version command increments a package's version field between releases. Options include patch (1.4.6 -> 1.4.7), minor, major, or a prerelease.

Native TypeScript compiler understands Deno's module resolution

Unlike running the standalone `tsgo` binary, Deno's integration with the native compiler understands Deno's module resolution and types, so `jsr:` and `npm:` specifiers and the `Deno` global all resolve as usual.

TypeScript is a first-class language in Deno

TypeScript files can be run directly with `deno run` without any compiler installation or build step. Configuration is optional; a `tsconfig.json` file works if already present, but is not required to get started.

Deno separates execution and type-checking

Deno treats executing TypeScript and type-checking as two separate concerns. When running `deno run` on a TypeScript file, Deno strips the types and passes the resulting JavaScript to V8; this does not check if types are correct. Type errors do not stop code from running unless explicitly checked with `deno check` or `deno run --check`.

deno check command for type checking

The `deno check` command runs the TypeScript compiler over code without executing it, equivalent to `tsc --noEmit` with strict mode enabled by default. It exits non-zero on errors, making it suitable for CI pipelines.

deno check accepts multiple formats

The `deno check` command accepts the following options: `deno check` to check the whole project, `deno check main.ts` or `deno check src/` to check specific files or directories, `deno check --all main.ts` to also type-check remote modules and npm dependencies, and `deno check --check-js main.js` to type-check JavaScript files without adding @ts-check to each one.

deno run --check for type-checking before execution

Adding `--check` to `deno run` causes type-checking to occur before execution. A type error stops the process before any code runs. Use `deno run --check=all main.ts` to include remote modules and npm packages in the check.

deno test and deno bench type-check by default

`deno test` and `deno bench` type-check by default. Pass `--no-check` to skip type-checking.

Deno strips types and caches emitted JavaScript internally

When executing TypeScript, Deno strips the types and caches the resulting JavaScript internally instead of writing it to disk. There is no `outDir`, `dist/` directory, or source map configuration to manage. Error stack traces still point directly at the original `.ts` sources.

Deno imports require real file extensions

In Deno, imports must use real file extensions on disk. For example, write `import { greet } from "./greet.ts"` to import a file named `greet.ts`. Under `tsc`, you would write `./greet.js` or enable `allowImportingTsExtensions`; Deno requires neither workaround since it never emits files.

Deno runs full TypeScript language including runtime-generating features

Deno runs all TypeScript language features, including those that generate runtime code: enums, namespaces with runtime values, and parameter properties. These features work with no flags. Node's type stripping only handles syntax it can erase and requires the experimental `--experimental-transform-types` flag for these features.

Deno type-checking uses strict mode by default

Deno type-checks in strict mode by default and also enables `noImplicitOverride`, which `tsc` leaves off even under `strict` mode.

Type-check JavaScript files with @ts-check pragma

JavaScript files can be opted into type-checking by adding a `// @ts-check` pragma at the top of the file. This checks the single file; the checker flags the same errors it would in TypeScript.

Type JavaScript with JSDoc comments

JavaScript files can provide type information using JSDoc comments, which the type checker reads. Type annotations cannot be used directly in JavaScript, but JSDoc syntax provides the same information. For example: `/** @param {number} a */` annotates a parameter as a number.

Provide declaration files for untyped JavaScript modules

When importing an untyped JavaScript module from TypeScript, the checker assumes everything exported is `any`. Supply a `.d.ts` declaration file to fix this, unless the JavaScript is already annotated with JSDoc.

Deno does not auto-detect .d.ts files next to .js files

Unlike `tsc`, Deno does not automatically pick up a `.d.ts` file sitting next to a `.js` file with the same basename. You must explicitly specify where the declaration file is, either in the JavaScript source or at the import site.

Use @ts-self-types to declare types in the source

Use the `@ts-self-types` directive in a `.js` file to point to a declaration file, so every importer gets the types for free. For example: `// @ts-self-types="./add.d.ts"` in the JavaScript source.

Use @ts-types to annotate import with declaration file

If you cannot modify the JavaScript source, use the `@ts-types` directive at the import site to annotate where the declaration file is. For example: `// @ts-types="./add.d.ts"` before an import statement, or `// @ts-types="npm:@types/lodash"` to point at a types package.

Add @types packages as dependencies for automatic resolution

For npm packages without type information, add the corresponding `@types` package as a dependency using `deno add`. When `@types` packages live in a local `node_modules` directory, Deno picks them up automatically for every import of the package without requiring `@ts-types` annotations.

Use @ts-types with dynamic imports for typing

The `@ts-types` directive only applies to static `import` statements, not to dynamic `import()`. To type a dynamic import of an untyped module, use a type assertion: `const { markedTerminal } = await import("npm:marked-terminal@7") as typeof import("npm:@types/marked-terminal@6");`

X-TypeScript-Types header for HTTP modules

Servers hosting JavaScript modules can advertise a declaration file in an `X-TypeScript-Types` response header, which Deno resolves relative to the module URL and uses during type checking. CDNs such as esm.sh set this header automatically.

Use declare global with var for augmenting global types

When polyfilling global APIs, use `declare global` with `var` to teach the type checker about the global, since Deno 2 has no `window` object and globals live on `globalThis`. Example: `declare global { var polyfilledAPI: () => string; }`

Avoid global augmentation in favor of ordinary imports

Global augmentation should be avoided when an ordinary import will do, as globals can cause naming conflicts, make code harder to reason about, and are not supported when publishing to JSR.

Deno standard library includes HTTP and file system modules

Deno comes with a standard library that includes modules for common tasks like HTTP servers, file system operations, and more.

Give your agent this brain