Skip to content
aviral gupta

// B1.3 · ~30 min · Beginner

A first tsconfig.json (strict by default)

After this lesson you can write a small tsconfig.json, say what strict checks, choose the files tsc checks, and explain each option of the course tsconfig.

Lesson 3 of 5 in B1 Setup and the basics

You will be able to

  • Write a minimal tsconfig.json and say what strict, on by default, checks
  • Use include, exclude and noEmit to choose which files tsc checks and whether it writes JavaScript
  • Explain the options of the course tsconfig and run tsc so that it uses the tsconfig
  1. Warm-up · Activity 1 of 7

    Warm-up from the last two lessons. Which of these are true? Pick all that apply.

    Select all that apply.

  2. Predict · Activity 2 of 7

    Predict. main.ts holds function greet(name) { return "Hello, " + name; } and a call. Next to it is this tsconfig.json, with nothing in it. What does npx tsc report?

    {}
  3. Practice · Activity 3 of 7

    Fill in the option that makes tsc only check, without writing any JavaScript files.

    {
      "compilerOptions": {
        "____": true
      }
    }
    "": true
  4. Practice · Activity 4 of 7

    The folder holds tsconfig.json and main.ts, side by side, and nothing else. What does npx tsc report?

    {
      "compilerOptions": {"noEmit": true},
      "include": ["src/**/*.ts"]
    }
  5. Practice · Activity 5 of 7

    Match each option of the course tsconfig to what it does.

  6. Brain teaser · Activity 6 of 7

    Brain teaser. The course folder holds main.ts and the course tsconfig.json. To check just this one file, you run npx tsc main.ts. What happens?

  7. Apply · Activity 7 of 7

    Mini-task on your computer (TypeScript installed as in the last lesson). In a new folder, put main.ts inside a src folder and write your own tsconfig.json: strict on, noEmit on, and include only "src/**/*.ts". Run npx tsc --showConfig to see the settings tsc will use, then npx tsc. Remove noEmit, run npx tsc again and look for the new file. Finally run npx tsc src/main.ts and read the error.

    Check your work against this list

Build it yourself

Read the worked example, then write the exercises. Your code runs in your browser or on your computer and is never uploaded.

Worked example

What strict catches, and how the code handles it

strict is on in the course tsconfig, so tsc knows that find returns undefined when nothing matches. Every place that uses the result handles that case with ??, which gives a fallback for undefined. Run npx tsc: no errors. Then node main.ts. Now change the last line to found.length and run npx tsc again: error TS18048: 'found' is possibly 'undefined'.

main.ts

// strict is on, so tsc knows that find() may return undefined.
const names: string[] = ["Ada", "Grace", "Linus"];
const found = names.find((name) => name.startsWith("G"));
const missing = names.find((name) => name.startsWith("Z"));

console.log("found:", found ?? "nobody");
console.log("missing:", missing ?? "nobody");
console.log("letters:", (found ?? "").length);

Run it with

npx tsc
node main.ts

Output

found: Grace
missing: nobody
letters: 5
  • find returns the first match, or undefined when there is none, as missing shows.
  • With strictNullChecks, part of strict, tsc makes you handle undefined before you use the value.
  • value ?? fallback gives the fallback only when value is undefined or null.
  • With "strict": false, missing.length would type-check, and node main.ts would then crash, because missing is undefined.
Change it and run it

Tab indents and Shift+Tab outdents. To leave the editor with the keyboard, press Esc, then Tab.

The first run downloads the TypeScript compiler (up to 2.1 MB) and keeps it cached. Your code stays on your device.

Exercises

Exercise 1 of 2

Handle the case find() cannot cover

firstLong should return the first word longer than five letters, in capitals, or "" (empty text) when there is none. strict is on, and tsc reports that found is possibly undefined; for a list without a long word, the function also crashes. Handle the undefined case in the return line.

Tab indents and Shift+Tab outdents. To leave the editor with the keyboard, press Esc, then Tab.

The first run downloads the TypeScript compiler (up to 2.1 MB) and keeps it cached. Your code stays on your device.

Hints
  1. Hint 1

    tsc reports main.ts(3,10): error TS18048: 'found' is possibly 'undefined'. That is strictNullChecks, part of strict.

  2. Hint 2

    find returns undefined when no word matches, and undefined has no toUpperCase.

  3. Hint 3

    Give a fallback first: return (found ?? "").toUpperCase();

Show a solution

One way to solve it. Yours can look different and still pass the checks.

export function firstLong(words: string[]): string {
  const found = words.find((word) => word.length > 5);
  return (found ?? "").toUpperCase();
}
Run it on your computer

Install TypeScript 7.0 or newer. Save these files in one folder, open a terminal in that folder, and run the commands below.

main.ts

export function firstLong(words: string[]): string {
  const found = words.find((word) => word.length > 5);
  return found.toUpperCase();
}

main.test.ts

import {test} from 'node:test';
import assert from 'node:assert/strict';
import {firstLong} from './main.ts';

test('finds the first long word', () => {
  assert.equal(firstLong(['go', 'typescript', 'javascript']), 'TYPESCRIPT', 'firstLong(["go", "typescript", "javascript"]) should be "TYPESCRIPT"');
});

test('returns empty text when no word is long', () => {
  assert.equal(firstLong(['go', 'ts']), '', 'firstLong(["go", "ts"]) should be ""');
});

package.json

{
  "type": "module"
}

tsconfig.json

{
  "compilerOptions": {
    "target": "esnext",
    "module": "nodenext",
    "lib": [
      "esnext",
      "dom"
    ],
    "types": [],
    "strict": true,
    "noEmit": true,
    "erasableSyntaxOnly": true,
    "verbatimModuleSyntax": true,
    "allowImportingTsExtensions": true
  },
  "include": [
    "**/*.ts"
  ],
  "exclude": [
    "**/*.test.ts"
  ]
}

npx tsc needs TypeScript in the folder: run npm install --save-dev typescript there once. tsc checks the types; Node.js runs main.ts by removing them.

Run the program:

npx tsc
node main.ts

Run the checks (needs learnrun.js in the same folder):

npx tsc
node --test
Download learnrun.js

Exercise 2 of 2

Apply the default of strict

strictIsOn gets the value of "strict" from a tsconfig: true, false, or nothing at all when the option is left out (setting?: means the caller may leave it out; it is then undefined). It should return whether strict is on, and left out means the default, true. tsc rejects the return line. Fix it.

Tab indents and Shift+Tab outdents. To leave the editor with the keyboard, press Esc, then Tab.

The first run downloads the TypeScript compiler (up to 2.1 MB) and keeps it cached. Your code stays on your device.

Hints
  1. Hint 1

    tsc reports main.ts(3,3): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. setting may be undefined, and the function promises a boolean.

  2. Hint 2

    When setting is undefined, return the default of strict in TypeScript 7.0.

  3. Hint 3

    return setting ?? true; keeps false as false, because ?? only replaces undefined and null.

Show a solution

One way to solve it. Yours can look different and still pass the checks.

// The value of "strict" in a tsconfig: true, false, or left out (undefined).
export function strictIsOn(setting?: boolean): boolean {
  return setting ?? true;
}
Run it on your computer

Install TypeScript 7.0 or newer. Save these files in one folder, open a terminal in that folder, and run the commands below.

main.ts

// The value of "strict" in a tsconfig: true, false, or left out (undefined).
export function strictIsOn(setting?: boolean): boolean {
  return setting;
}

main.test.ts

import {test} from 'node:test';
import assert from 'node:assert/strict';
import {strictIsOn} from './main.ts';

test('left out means the default: on', () => {
  assert.equal(strictIsOn(), true, 'strictIsOn() should be true');
});

test('true means on', () => {
  assert.equal(strictIsOn(true), true, 'strictIsOn(true) should be true');
});

test('false means off', () => {
  assert.equal(strictIsOn(false), false, 'strictIsOn(false) should be false');
});

package.json

{
  "type": "module"
}

tsconfig.json

{
  "compilerOptions": {
    "target": "esnext",
    "module": "nodenext",
    "lib": [
      "esnext",
      "dom"
    ],
    "types": [],
    "strict": true,
    "noEmit": true,
    "erasableSyntaxOnly": true,
    "verbatimModuleSyntax": true,
    "allowImportingTsExtensions": true
  },
  "include": [
    "**/*.ts"
  ],
  "exclude": [
    "**/*.test.ts"
  ]
}

npx tsc needs TypeScript in the folder: run npm install --save-dev typescript there once. tsc checks the types; Node.js runs main.ts by removing them.

Run the program:

npx tsc
node main.ts

Run the checks (needs learnrun.js in the same folder):

npx tsc
node --test
Download learnrun.js

Common mistakes

Using a value that may be undefined

const names = ["Ada", "Grace"];
const found = names.find((name) => name.startsWith("G"));
console.log(found.toUpperCase());

What tsc or Node.js prints

main.ts(3,13): error TS18048: 'found' is possibly 'undefined'.

Why, and the fix

find returns undefined when nothing matches, and strictNullChecks, part of strict, will not let you call a method on a value that may be undefined. Here a name does match, but tsc checks every case, not this run. Handle the case: (found ?? "").toUpperCase(). Turning strict off would silence tsc, and the program would crash as soon as nothing matches.

An enum, which Node.js cannot strip

enum Size {
  Small,
  Large
}

console.log(Size.Large);

What tsc or Node.js prints

main.ts(1,6): error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.

Why, and the fix

An enum is TypeScript syntax that produces code at run time, so Node.js cannot run it by stripping types: node main.ts stops with an error too. The course tsconfig sets erasableSyntaxOnly, so tsc reports it first. Use plain values instead, such as const Size = {Small: 0, Large: 1};.

Using Node's process without its types

console.log("arguments:", process.argv.length);

What tsc or Node.js prints

main.ts(1,27): error TS2591: Cannot find name 'process'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node` and then add 'node' to the types field in your tsconfig.

Why, and the fix

process belongs to Node.js, and its declarations come from the @types/node package. The course tsconfig sets "types": [], so no such package is loaded (this needs Node.js; run it locally). As the message says, a Node project installs @types/node and lists "node" in types. The course keeps to programs without Node's own APIs until later modules.

TypeScript in the browser: the TypeScript 6.0.3 compiler, Apache-2.0, then your browser’s own engine. Licence and source

Exit ticket

5 questions, no hints. Score 80% or more to complete the lesson.

Finish every activity above to unlock the exit ticket.

Report a problem

Spotted something wrong or unclear? Say what, and it will be checked and fixed.

#

At least 20 characters.

Only if you want a reply.

Key ideas

A tsconfig.json marks a project

A tsconfig.json makes its folder the root of a TypeScript project. compilerOptions says how to check; include and exclude say which files. Every option you leave out keeps the compiler's default, so even {} is a valid tsconfig, and npx tsc --init writes a longer starter file with comments. Since TypeScript 6.0, and so in 7.0, strict is on by default: {} already reports a parameter without a type. strict switches on a family of checks, among them noImplicitAny (no silent any) and strictNullChecks (a value that may be undefined must be handled before it is used). "strict": false turns them all off; one of them can be turned off alone, as in "noImplicitAny": false.

Which files, and what tsc writes

include lists the project's files as patterns: "**/*.ts" means every .ts file in this folder and every folder below it. Without include, tsc takes **/*, every file it can check. exclude removes files from what include found, such as "**/*.test.ts". If nothing matches, tsc stops with No inputs were found in config file. Without noEmit, tsc also writes JavaScript, main.js next to main.ts, and it does so even when it reports errors. noEmit makes tsc a checker only, which is all you need when node main.ts runs the .ts file itself. A misspelt option is not ignored: "stict" gives error TS5023: Unknown compiler option 'stict'.

The course tsconfig, option by option

target esnext and module nodenext: modern JavaScript, and files are ES modules, as package.json's "type": "module" says, so imports name their extension. lib esnext and dom: declarations of the built-ins; console is declared in dom. types []: no @types packages, so tsc does not know Node's process. strict and noEmit as above. erasableSyntaxOnly: only TypeScript syntax that Node.js can strip, so no enum. verbatimModuleSyntax: a type-only import must say import type. allowImportingTsExtensions: allows "./format.ts", and only with noEmit. Run npx tsc: npx tsc main.ts next to a tsconfig.json stops with error TS5112; tsc --ignoreConfig main.ts checks that file with default settings instead.

Sources

Last reviewed September 30, 2026