TypeScript Intermediate: Generics and Utility Types
Modules, tsconfig and Projects
In this lesson you will
- Export and import values and types between files
- Read the main options in tsconfig.json
- Explain declaration files and the @types packages
Introduction
So far every example was a single file. Real projects have many, and they need a place to say how strict the compiler should be. This lesson shows how files share code, and how a project is configured. The code samples here are shown for reading and are not runnable in the browser editors, because they need several files.
Modules: splitting code into files
Any file that has a top-level import or export is a module. It has its own scope. Things are private unless exported.
TypeScript
// shapes.ts
export interface Point {
x: number;
y: number;
}
export function distance(a: Point, b: Point): number {
return Math.hypot(a.x - b.x, a.y - b.y);
}
const secret = 42; // not exported, so private to this fileTypeScript
// main.ts
import { distance, type Point } from "./shapes";
const a: Point = { x: 0, y: 0 };
const b: Point = { x: 3, y: 4 };
console.log(distance(a, b)); // 5exportmakes a value or type available to other files.import { ... } from "./file"brings it in. Note there is no.tsending in the path.export defaultandimport name fromalso exist, but named exports are easier to rename and search for.
import type
Types do not exist at runtime, so importing one only matters to the compiler. Mark it with type, as with type Point above, or import a whole line:
TypeScript
import type { Point } from "./shapes";This makes it clear nothing is needed at runtime, and the compiler removes the line from the output entirely.
Quick quiz
What makes a TypeScript file a module?
tsconfig.json
A project has a tsconfig.json file at its root. It tells the compiler which files to include and how strictly to check them. Here is a typical small one:
JSON
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"noUncheckedIndexedAccess": true,
"skipLibCheck": true,
"outDir": "dist"
},
"include": ["src"]
}target: which JavaScript version to produce.moduleandmoduleResolution: how imports are written and found.strict: turns on a group of safety checks (see below).outDir: where compiled JavaScript goes.include: which folders to compile.
Run the compiler with npx tsc. Add --noEmit to only check types without producing files, which is what many projects do when another tool builds the code.
Strict mode
"strict": true is shorthand for a family of checks. The ones you have met are:
noImplicitAny: errors when TypeScript would silently fall back toany.strictNullChecks:nullandundefinedare separate types you must handle.strictFunctionTypesandstrictPropertyInitialization: stricter rules for functions and class fields.
Start new projects with strict on. Turning it on later in a large codebase is painful. noUncheckedIndexedAccess goes further: reading array[0] gives T | undefined, because the index might not exist.
Declaration files and @types
JavaScript libraries do not carry types. A declaration file (ending .d.ts) describes the types of JavaScript code, with no implementation.
TypeScript
// legacy.d.ts
declare function legacyAdd(a: number, b: number): number;Many libraries ship their own .d.ts files. For popular ones that do not, the community maintains types on DefinitelyTyped, installed as separate packages:
Terminal
npm install --save-dev @types/nodeNow import fs from "node:fs" is fully typed. If TypeScript says it "could not find a declaration file for module", look for an @types/... package.
Quick quiz
What does the strict option in tsconfig.json do?
Try it yourself
This program compiles in the editor, but it crashes when it runs, because the array is empty. In a project with noUncheckedIndexedAccess on, TypeScript would flag the last line, since first is string | undefined. Fix the program with a check, so that it prints no names yet instead of crashing.
Summary
- A file with a top-level
importorexportis a module. Anything not exported stays private. import typemarks imports that exist only for the compiler.tsconfig.jsonsets target, module system, strictness and which files to compile. Runnpx tsc.- Turn
stricton for new projects..d.tsfiles and@typespackages describe untyped JavaScript.
Lesson complete
+20 XP
Nice work. Keep going while it is fresh.
Sources and further reading