Quick start

Type-check your JavaScript in five minutes

Three ways to get TypeScript's checker reading your .js files. Each ends in the same place: a jsconfig.json, an npm run lint that runs tsc, and type errors in your editor as you type.

  • 0 build steps
  • 1 config file
  • 5 minutes

Before you start

You need Node.js and npm, and a folder with some JavaScript in it (an empty folder works too). Nothing here changes how your code runs: the checker reads your files and reports problems, and your JavaScript ships exactly as you wrote it.

Path 1: write jsconfig.json yourself

The recommended path: four short steps, and you know what every line of the config does.

  1. Install TypeScript

    TypeScript is a development dependency: it checks your code and never runs in production. In a folder without a package.json, create one first and mark the project as ES modules.

    Terminal
    npm init -y
    npm pkg set type=module
    npm install --save-dev typescript
  2. Create jsconfig.json

    Next to package.json:

    jsconfig.json
    {
      "compilerOptions": {
        "checkJs": true,
        "noEmit": true,
        "strict": true,
        "module": "nodenext",
        "target": "es2022"
      }
    }

    checkJs reports errors in .js files, noEmit stops tsc from writing output, and strict turns on the strict family of checks, including the one behind TS7006. module: "nodenext" makes the checker resolve imports the way Node.js does, and target says which JavaScript features your code may use.

  3. Add a lint script and run it

    Terminal
    npm pkg set scripts.lint="tsc -p jsconfig.json"
    npm run lint

    No output means no errors. Run the same script in CI to keep it that way.

  4. Annotate your first function

    Add a JSDoc comment with the types. The checker holds every caller to them, and your editor shows them on hover.

    index.js TypeScript 5.9.3 · checked 21 October 2026
    /**
     * @param {string} name
     * @returns {string}
     */
    export function greet(name) {
      return `Hello, ${name}!`;
    }
    
    console.log(greet("world"));
    A first function, typed with JSDoc.
    jsconfig.json for this example
    {
      "compilerOptions": {
        "checkJs": true,
        "noEmit": true,
        "strict": true,
        "module": "nodenext",
        "target": "es2022"
      }
    }

Path 2: generate it with tsc --init

TypeScript can write the config file for you. Pass the options as flags, then rename the file it writes:

Terminal
npm install --save-dev typescript
npx tsc --init --allowJs --checkJs --noEmit --strict --module nodenext --target es2024 --types node
mv tsconfig.json jsconfig.json

In TypeScript 5.9, tsc --init also writes defaults of its own. sourceMap, declaration and declarationMap only matter when tsc writes files, which noEmit stops. noUncheckedIndexedAccess and exactOptionalPropertyTypes make checking stricter than strict alone. verbatimModuleSyntax, isolatedModules, noUncheckedSideEffectImports and moduleDetection tighten how imports and modules are checked, skipLibCheck skips your dependencies' .d.ts files, and jsx does nothing in files without JSX. Keep the ones you want, delete the rest, or let the jsconfig generator print a tsc --init command that switches them off.

Install typescript before you run npx tsc. Without it, npx fetches an unrelated npm package named tsc instead of TypeScript.

Renaming the file is optional, since tsc -p reads either name. Calling it jsconfig.json tells editors and readers the project is JavaScript, and gives it JavaScript-friendly defaults such as allowJs. This example was checked with the exact file tsc --init wrote, renamed (open the config under the code to see it):

lines.js TypeScript 5.9.3 · checked 21 October 2026
import { readFile } from "node:fs/promises";

/**
 * @param {string} path
 * @returns {Promise<string[]>}
 */
export async function readLines(path) {
  const text = await readFile(path, "utf8");
  return text.split("\n");
}

const [first] = await readLines("notes.txt");
// With noUncheckedIndexedAccess, `first` is string | undefined.
console.log(first?.trim());
A script checked with the config tsc --init writes, renamed to jsconfig.json.
jsconfig.json for this example
{
  // Visit https://aka.ms/tsconfig to read more about this file
  "compilerOptions": {
    // File Layout
    // "rootDir": "./src",
    // "outDir": "./dist",

    // Environment Settings
    // See also https://aka.ms/tsconfig/module
    "module": "nodenext",
    "target": "es2024",
    "types": ["node"],
    // For nodejs:
    // "lib": ["esnext"],
    // "types": ["node"],
    // and npm install -D @types/node

    // Other Outputs
    "sourceMap": true,
    "declaration": true,
    "declarationMap": true,

    // Stricter Typechecking Options
    "noUncheckedIndexedAccess": true,
    "exactOptionalPropertyTypes": true,

    // Style Options
    // "noImplicitReturns": true,
    // "noImplicitOverride": true,
    // "noUnusedLocals": true,
    // "noUnusedParameters": true,
    // "noFallthroughCasesInSwitch": true,
    // "noPropertyAccessFromIndexSignature": true,

    // Recommended Options
    "strict": true,
    "jsx": "react-jsx",
    "verbatimModuleSyntax": true,
    "isolatedModules": true,
    "noUncheckedSideEffectImports": true,
    "moduleDetection": "force",
    "skipLibCheck": true,

    "allowJs": true,
    "checkJs": true,
    "noEmit": true,
  }
}

Path 3: scaffold it with jswt

jswt is a small command-line tool by AJ ONeal that sets up exactly this kind of project in one step. It is published on npm under the Mozilla Public License 2.0.

Terminal
npx -p jswt@2.x -- jswt init

It runs tsc --init with its own set of flags, renames the result to jsconfig.json, adds include and paths entries, and creates a few placeholder files. Version 2 sets up ES modules; version 1 is for CommonJS projects. Read its package page before you run it, as you would for any tool that writes files into your project.

The tool came out of the 2022 conference talk that first used this domain; the page on where the name comes from has the story.

Setups for your project shape

The config above suits a Node.js project. Each project shape has its own page with the matching config, types and scripts:

  • Project shape

    Node.js with ES modules

    Type-check a Node.js project written as ES modules: the jsconfig.json, @types/node, the npm scripts and the import rules that nodenext enforces.

  • Project shape

    Node.js with CommonJS

    Type-check a CommonJS Node.js project: require and module.exports with JSDoc, @types/node, and module nodenext reading "type": "commonjs".

  • Project shape

    Browser, no bundler

    Type-check JavaScript that the browser loads as module scripts: the DOM in lib, no Node.js types, and imports held to the exact paths a browser needs.

  • Project shape

    Library (publishing types)

    Publish a JavaScript package with types: JSDoc in the source, a second config that writes .d.ts files, and an exports map with a types condition.

  • Project shape

    Cloudflare Workers

    Type-check a Cloudflare Workers project written in JavaScript: the runtime types, an Env typedef for your bindings, @satisfies on the handler, no DOM in lib.

  • Project shape

    Deno

    Type-check JavaScript with Deno: deno check, checkJs and JSDoc, a jsconfig.json Deno reads next to package.json, and when Deno checks types.

  • Project shape

    Bun

    Type-check JavaScript that Bun runs: @types/bun, the module settings Bun recommends, and tsc -p jsconfig.json, since running a file does not check it.

  • Project shape

    Monorepo

    Type-check a JavaScript monorepo: one root jsconfig.json for all packages, a small one per package that extends it, and paths to the sources.

What to read next

  • @type: annotate a variable, cast an expression, type a whole function.
  • TS7006: the first error most projects see after turning on strict.
  • VS Code: make the editor use the same TypeScript as npm run lint.
  • jsconfig generator: a config for your project shape and strictness.

Last reviewed 20 October 2026.