This chapter gives the bird’s eye view of how TypeScript works: What is the structure of a typical TypeScript project? What is compiled and how? How can we use IDEs to write TypeScript?
This is one possible file structure for TypeScript projects:
typescript-project/
dist/
ts/
src/
main.ts
util.ts
test/
util_test.ts
tsconfig.json
Explanations:
ts/
contains the TypeScript files:
ts/src/
contains the actual code.ts/test/
contains tests for the code.dist/
is where the output of the compiler is stored.ts/
to JavaScript files in dist/
. For example:
ts/src/main.ts
is compiled to dist/src/main.js
(and possibly other files)tsconfig.json
is used to configure the TypeScript compiler.tsconfig.json
The contents of tsconfig.json
look as follows:
{
"compilerOptions": {
"rootDir": "ts",
"outDir": "dist",
"module": "commonjs",
···
}
}
We have specified that:
ts/
.dist/
.Two popular IDEs for JavaScript are:
The observations in this section are about Visual Studio Code, but may apply to other IDEs, too.
One important fact to be aware of is that Visual Studio Code processes TypeScript source code in two independent ways:
tsc
has a --watch
mode that watches input files and compiles them to output files whenever they change. As a consequence, whenever we save a TypeScript file in the IDE, we immediately get the corresponding output file(s).tsc
from within Visual Studio Code. In order to do so, it must be installed either inside project that we are currently working on or globally (via the Node.js package manager npm).Given a TypeScript file main.ts
, the TypeScript compiler can produce several kinds of artifacts. The most common ones are:
main.js
main.d.ts
(contains type information; think .ts
file minus the JavaScript code)main.js.map
TypeScript is often not delivered via .ts
files, but via .js
files and .d.ts
files:
A source map specifies for each part of the output code in main.js
, which part of the input code in main.ts
produced it. Among other things, this information enables runtime environments to execute JavaScript code, while showing the line numbers of the TypeScript code in error messages.
The npm registry is a huge repository of JavaScript code. If we want to use a JavaScript package from TypeScript, we need type information for it:
.d.ts
files or even the complete TypeScript code.The declaration files of DefinitelyTyped reside in the @types
namespace. Therefore, if we need a declaration file for a package such as lodash
, we have to install the package @types/lodash
.
The TypeScript compiler can also process plain JavaScript files:
With the option --allowJs
, the TypeScript compiler copies JavaScript files in the input directory over to the output directory. Benefit: When migrating from JavaScript to TypeScript, we can start with a mix of JavaScript and TypeScript files and slowly convert more JavaScript files to TypeScript.
With the option --checkJs
, the compiler additionally type-checks JavaScript files (--allowJs
must be on for this option to work). It does so as well as it can, given the limited information that is available. Which files are checked can be configured via comments inside them:
// @ts-nocheck
, it will not be type-checked.--checkJs
, the comment // @ts-check
can be used to type-check individual JavaScript files.The TypeScript compiler uses static type information that is specified via JSDoc comments (see below for an example). If we are thorough, we can fully statically type plain JavaScript files and even derive declaration files from them.
With the option --noEmit
, the compiler does not produce any output, it only type-checks files.
This is an example of a JSDoc comment that provides static type information for a function add()
:
/**
* @param {number} x - The first operand
* @param {number} y - The second operand
* @returns {number} The sum of both operands
*/
function add(x, y) {
+ y;
return x }
More information: Type-Checking JavaScript Files in the TypeScript Handbook.