Skip to content

Commit b817055

Browse files
bartlomiejuclaude
andauthored
docs: improve TypeScript and tsconfig.json documentation (#3007)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 10cc041 commit b817055

3 files changed

Lines changed: 87 additions & 217 deletions

File tree

runtime/fundamentals/configuration.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -346,8 +346,14 @@ sharing code.
346346

347347
:::
348348

349-
See also
350-
[Configuring TypeScript in Deno](/runtime/reference/ts_config_migration/).
349+
If you’re migrating from Node.js, your existing `tsconfig.json` files work out
350+
of the box with Deno. See
351+
[Using tsconfig.json with Deno](/runtime/fundamentals/typescript/#using-tsconfigjson-with-deno)
352+
for details.
353+
354+
For the full list of supported compiler options, library configuration, and
355+
advanced settings, see
356+
[Configuring TypeScript](/runtime/reference/ts_config_migration/).
351357

352358
## Unstable features
353359

runtime/fundamentals/typescript.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,3 +319,67 @@ file, in the `compilerOptions.types` array:
319319
```
320320

321321
This will also augment the global scope with the `polyfilledAPI` function.
322+
323+
## Configuring TypeScript compiler options
324+
325+
Deno uses strict and modern TypeScript defaults out of the box, so most projects
326+
don't need any configuration. When you do need to customize compiler behavior,
327+
use the `compilerOptions` field in
328+
[`deno.json`](/runtime/fundamentals/configuration/):
329+
330+
```json title="deno.json"
331+
{
332+
"compilerOptions": {
333+
"noUnusedLocals": true,
334+
"noUnusedParameters": true,
335+
"noImplicitReturns": true
336+
}
337+
}
338+
```
339+
340+
See the
341+
[full list of supported compiler options](/runtime/reference/ts_config_migration/#ts-compiler-options).
342+
343+
## Using `tsconfig.json` with Deno
344+
345+
If you're migrating a TypeScript project from Node.js, your existing
346+
`tsconfig.json` files work with Deno's type checker and LSP out of the box. Deno
347+
automatically discovers `tsconfig.json` files in directories that also contain a
348+
`deno.json` or `package.json`.
349+
350+
```
351+
my-project/
352+
├── deno.json
353+
├── tsconfig.json # ← discovered automatically
354+
├── src/
355+
│ └── main.ts
356+
└── packages/
357+
└── lib/
358+
├── package.json
359+
└── tsconfig.json # ← also discovered
360+
```
361+
362+
Deno supports the standard `tsconfig.json` fields: `extends`, `files`,
363+
`include`, `exclude`, `references`, and `compilerOptions`.
364+
365+
:::note
366+
367+
For Deno-first projects, prefer `compilerOptions` in `deno.json` over a separate
368+
`tsconfig.json`. The `tsconfig.json` compatibility exists primarily to ease
369+
migration of existing Node.js projects.
370+
371+
:::
372+
373+
### Precedence rules
374+
375+
When both `deno.json` and `tsconfig.json` exist:
376+
377+
1. `compilerOptions` in a parent `deno.json` take precedence over any
378+
`tsconfig.json`.
379+
2. A `tsconfig.json` reference takes precedence over its referrer.
380+
3. For root references, a more deeply nested `tsconfig.json` takes precedence
381+
(e.g. `foo/bar/tsconfig.json` over `foo/tsconfig.json`).
382+
383+
For the full details on `tsconfig.json` compatibility, compiler options, and
384+
library configuration, see the
385+
[Configuring TypeScript](/runtime/reference/ts_config_migration/) reference.

runtime/reference/ts_config_migration.md

Lines changed: 15 additions & 215 deletions
Original file line numberDiff line numberDiff line change
@@ -14,70 +14,10 @@ oldUrl:
1414
- /runtime/fundamentals/types/
1515
---
1616

17-
Deno’s flexibility shines in its equal treatment of TypeScript and JavaScript.
18-
Whether you’re transitioning from JavaScript to TypeScript or vice versa, Deno
19-
has features to ease the journey.
20-
21-
## Type Checking JavaScript
22-
23-
You may wish to make your JavaScript more type-sound without adding type
24-
annotations everywhere. Deno supports using the TypeScript type checker to type
25-
check JavaScript. You can mark individual files by adding the check JavaScript
26-
pragma to the file:
27-
28-
```js
29-
// @ts-check
30-
```
31-
32-
This will cause the type checker to infer type information about the JavaScript
33-
code and raise any issues as diagnostic issues.
34-
35-
These can be turned on for all JavaScript files in a program by providing a
36-
configuration file with the check JS option set to `true`, as below. Then use
37-
the `--config` option when running on the command line.
38-
39-
```json
40-
{
41-
"compilerOptions": {
42-
"checkJs": true
43-
}
44-
}
45-
```
46-
47-
## Using JSDoc in JavaScript
48-
49-
When type-checking JavaScript or importing JavaScript into TypeScript, JSDoc
50-
annotations can provide additional type information beyond what can just be
51-
inferred from the code itself. Deno supports this seamlessly if you annotate
52-
your code inline with the supported
53-
[TypeScript JSDoc](https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html).
54-
55-
For example to set the type of an array use the following JSDoc comment:
56-
57-
```js
58-
/** @type {string[]} */
59-
const a = [];
60-
```
61-
62-
## Skipping type checking
63-
64-
You might have TypeScript code that you are experimenting with, where the syntax
65-
is valid but not fully type safe. You can bypass type checking for a whole
66-
program by passing the `--no-check` flag.
67-
68-
You can also skip whole files being type checked, including JavaScript if you
69-
have check JS enabled, by using the `nocheck` pragma:
70-
71-
```js
72-
// @ts-nocheck
73-
```
74-
75-
## Renaming JS files to TS files
76-
77-
TypeScript files benefit from the TypeScript compiler being able to do more
78-
thorough safety checks of your code. This is often referred to as _strict mode_.
79-
When you rename a `.js` file to `.ts` you'll might see new type errors that you
80-
TypeScript wasn't able to detect before.
17+
This page covers advanced TypeScript configuration in Deno, including compiler
18+
options, `tsconfig.json` compatibility, and library targeting. For an
19+
introduction to using TypeScript with Deno, see
20+
[TypeScript support](/runtime/fundamentals/typescript/).
8121

8222
## Configuring TypeScript in Deno
8323

@@ -274,151 +214,15 @@ code.
274214

275215
## Types and Type Declarations
276216

277-
Deno applies a design principle of _no non-standard module resolution_. When
278-
TypeScript checks a file, it focuses solely on its types. In contrast, the `tsc`
279-
compiler employs intricate logic to resolve those types. By default, `tsc`
280-
expects ambiguous module specifiers with extensions (e.g., `.ts`, `.d.ts` or
281-
`.js`). Deno, however, deals with explicit specifiers.
282-
283-
Here’s where it gets interesting: Imagine you want to consume a TypeScript file
284-
that’s already transpiled to JavaScript, along with its type definition file
285-
(`mod.js` and `mod.d.ts`). If you import `mod.js` into Deno, it strictly follows
286-
your request and imports the JavaScript file. But here’s the catch: Your code
287-
won’t be as thoroughly type-checked as if TypeScript considered the `mod.d.ts`
288-
file alongside the `mod.js` file.
289-
290-
To address this, Deno offers two solutions, each catering to specific scenarios:
291-
292-
**As the Importer:** If you know what types should apply to a JavaScript module,
293-
you can enhance type checking by explicitly specifying the types.
294-
295-
**As the Supplier:** If you’re the provider or host of the module, everyone
296-
consuming it benefits without worrying about type resolution.
297-
298-
## Providing types when importing
299-
300-
If you are consuming a JavaScript module and you have either created types (a
301-
`.d.ts` file) or have otherwise obtained the types you want to use, you can
302-
instruct Deno to use that file when type checking, instead of the JavaScript
303-
file, using the `@ts-types` compiler hint.
304-
305-
For example if you have a JavaScript module, `coolLib.js`, and a separate
306-
`coolLib.d.ts` file, you would import it like this:
307-
308-
```ts
309-
// @ts-types="./coolLib.d.ts"
310-
import * as coolLib from "./coolLib.js";
311-
```
312-
313-
When you’re performing type checking on `coolLib` and using it in your file, the
314-
TypeScript type definitions from `coolLib.d.ts` will take precedence over
315-
examining the JavaScript file.
316-
317-
:::note
318-
319-
In the past the `@ts-types` directive was called `@deno-types`. This alias still
320-
works, but is not recommended anymore. Use `@ts-types`.
321-
322-
:::
323-
324-
## Providing types when hosting
217+
For information on providing type declarations for JavaScript modules (using
218+
`@ts-types`, `@ts-self-types`, `X-TypeScript-Types` headers, and `.d.ts` files),
219+
see
220+
[Providing declaration files](/runtime/fundamentals/typescript/#providing-declaration-files)
221+
in the TypeScript fundamentals guide.
325222

326-
If you have control over the module’s source code or how the file is hosted on a
327-
web server, there are two ways to let Deno know about the types for a specific
328-
module (which won’t require any special action from the importer).
329-
330-
### @ts-self-types
331-
332-
If you are providing a JavaScript file, and want to provide a declaration file
333-
that contains the types for this file, you can specify a `@ts-self-types`
334-
directive in the JS file, pointing to the declaration file.
335-
336-
For example, if you make a `coolLib.js` library, and write its type definitions
337-
in `coolLib.d.ts` the `ts-self-types` directive would look like this:
338-
339-
```js title="coolLib.js"
340-
// @ts-self-types="./coolLib.d.ts"
341-
342-
// ... the rest of the JavaScript ...
343-
```
344-
345-
### X-TypeScript-Types
346-
347-
Deno supports a header for remote modules that instructs Deno where to locate
348-
the types for a given module. For example, a response for
349-
`https://example.com/coolLib.js` might look something like this:
350-
351-
```console
352-
HTTP/1.1 200 OK
353-
Content-Type: application/javascript; charset=UTF-8
354-
Content-Length: 648
355-
X-TypeScript-Types: ./coolLib.d.ts
356-
```
357-
358-
When seeing this header, Deno would attempt to retrieve
359-
`https://example.com/coolLib.d.ts` and use that when type checking the original
360-
module.
361-
362-
## Using ambient or global types
363-
364-
Overall it is better to use module/UMD type definitions with Deno, where a
365-
module expressly imports the types it depends upon. Modular type definitions can
366-
express
367-
[augmentation of the global scope](https://www.typescriptlang.org/docs/handbook/declaration-files/templates/global-modifying-module-d-ts.html)
368-
via the `declare global` in the type definition. For example:
369-
370-
```ts
371-
declare global {
372-
var AGlobalString: string;
373-
}
374-
```
375-
376-
This would make `AGlobalString` available in the global namespace when importing
377-
the type definition.
378-
379-
In some cases though, when leveraging other existing type libraries, it may not
380-
be possible to leverage modular type definitions. Therefore there are ways to
381-
include arbitrary type definitions when type checking programmes.
382-
383-
### Triple-slash directive
384-
385-
This option couples the type definitions to the code itself. By adding a
386-
triple-slash `types` directive in a TS file (not a JS file!), near the type of a
387-
module, type checking the file will include the type definition. For example:
388-
389-
```ts
390-
/// <reference types="./types.d.ts" />
391-
```
392-
393-
The specifier provided is resolved just like any other specifier in Deno, which
394-
means it requires an extension, and is relative to the module referencing it. It
395-
can be a fully qualified URL as well:
396-
397-
```ts
398-
/// <reference types="https://deno.land/x/pkg@1.0.0/types.d.ts" />
399-
```
400-
401-
### Supplying "types" in deno.json
402-
403-
Another option is to provide a `"types"` value to the `"compilerOptions"` in
404-
your `deno.json`. For example:
405-
406-
```json title="deno.json"
407-
{
408-
"compilerOptions": {
409-
"types": [
410-
"./types.d.ts",
411-
"https://deno.land/x/pkg@1.0.0/types.d.ts",
412-
"/Users/me/pkg/types.d.ts"
413-
]
414-
}
415-
}
416-
```
417-
418-
Like the triple-slash reference above, the specifier supplied in the `"types"`
419-
array will be resolved like other specifiers in Deno. In the case of relative
420-
specifiers, it will be resolved relative to the path to the config file. Make
421-
sure to tell Deno to use this file by specifying `--config=path/to/file` flag.
223+
For information on augmenting global types using `declare global` or `.d.ts`
224+
files, see
225+
[Augmenting global types](/runtime/fundamentals/typescript/#augmenting-global-types).
422226

423227
## Type Checking Web Workers
424228

@@ -464,13 +268,9 @@ library files. For example:
464268
}
465269
```
466270

467-
Then when running deno subcommand, you would need to pass the
468-
`--config path/to/file` argument, or if you are using an IDE which leverages the
469-
Deno language server, set the `deno.config` setting.
470-
471-
If you also have non-worker scripts, you will either need to omit the `--config`
472-
argument, or have one that is configured to meet the needs of your non-worker
473-
scripts.
271+
If you also have non-worker scripts, consider using
272+
[workspaces](/runtime/fundamentals/workspaces/) so each workspace member can
273+
have its own `compilerOptions`.
474274

475275
## Important points
476276

0 commit comments

Comments
 (0)