Imports
How the compiler handles each import of an installable file.
Resolution
The compiler collects an import record for each reference in a file, then resolves it, including tsconfig paths.
| Kind | Syntax |
|---|---|
import-statement | import ... from "x", export ... from "x" |
dynamic-import | import("x") |
new-url | new URL("./x", import.meta.url) |
| The import resolves to | Installed code |
|---|---|
| a Node.js built-in, or a macro | unchanged |
| a package outside of registries | unchanged, added to dependencies |
a path under external | unchanged |
a file matching a rule in files | relative import of the installed file |
a file matching a rule with preserve | package import, or relative if installed |
| a file exported by its package, without a rule | package import |
| anything else | compilation error |
Files excluded from tsconfig.json
A file written for the consumer's codebase is often excluded from your tsconfig.json, so paths
no longer apply to it and @/lib/source fails as a missing dependency. Give it a tsconfig.json:
{
"extends": "../tsconfig.json",
"include": ["build-graph.ts"],
"exclude": []
}Package Imports
Installed code often needs things that must stay in your package, like React contexts, which are only the same instance when imported from the package.
You don't declare them. The compiler follows the re-exports of each entry, and knows where every name is publicly available.
export * from "./context";
export { useTheme as useAcmeTheme } from "./theme";import { useCtx } from "../context";
import { useTheme, type Theme } from "../theme";
import * as icons from "../icons";- Names are matched individually, renamed exports are handled.
- Namespace, side-effect and dynamic imports need the file to be an entry itself.
- When a name is exported from multiple entries, the first one in
exportswins. - Private packages (
"private": true) are never imported, their files need a rule.
Errors
An import that cannot be installed nor swapped fails the compilation, with all problems reported at once:
src/card/index.tsx: "../theme" matches no rule in `files` of registry "acme-ui",
and internalOnly of it is not a public export of "acme-ui". Add a rule for theme.ts,
or export it from the package.This is checked against your source, so a registry never ships an import that your package doesn't satisfy.
Cross-Registry Imports
Imports of another registry in the same compilation follow the same table, whether written as a relative path or a package specifier.
// matches a rule of `acme-ui` -> relative import of the installed button
import { Button } from "acme-ui/button";
// no rule, but an entry -> unchanged
import { useCtx } from "acme-ui";Last updated on