In this blog post we look at:
.js
, .js.map
, .d.ts
, .d.ts.map
, .ts
Currently, the TypeScript compiler tsc
performs three tasks:
To make all of that happen, tsc
needs to be configured via a tsconfig.json
file which influences type checking and the emitted JavaScript code. As a result, there are many different “dialects” of TypeScript, depending on how strict type checking is – as specified in tsconfig.json
.
For a library file util.ts
, we get the best development experience if we deploy the following files:
util.js
: the runtime functionalityutil.js.map
: a source map that maps source code locations in util.js
to source code locations in util.ts
. That enables functionality such as showing stack traces for util.ts
while running util.js
and showing .ts
code while debugging .js
code.util.d.ts
: the typesutil.d.ts.map
: a declaration map that maps source code locations in util.d.ts
to source code locations in util.ts
. That enables functionality such as going to the definition of a type.util.ts
: included because it is the target of the source map and the declaration map.Except for util.ts
, it helps if all files sit next to each other: Then we only have to point the package exports to util.js
and TypeScript will automatically find the other files.
Part of the reason why tsc
is relatively slow is that it parses the TypeScript syntax and then has to perform costly semantic analyses to emit JavaScript and declarations:
tsc
has to figure out which constructs are JavaScript and which constructs are type-related.tsc
has to perform type analyses because there may be inferred types: The types of variables, the return types of functions, etc.Recent advances are about emitting both kinds of code via purely syntactic analyses – by forcing us to write simpler TypeScript that does not require semantic analyses:
type
.string
from a string literal is acceptable, inferring a type from a function call is not.Note that we don’t need a tsconfig.json
if we emit TypeScript via type stripping and declarations via isolated declarations. We only need it for type checking. That clarifies its role.
The following platforms let us run TypeScript directly:
JSR lets us upload packages with TypeScript files:
.js
files and .d.ts
files are generated on demand – which is fast because type stripping and a technique called no slow types (which is similar to isolated declarations) are used..d.ts
Points in favor of .d.ts
:
They make type-checking faster: When importing from a dependency:
.d.ts
file, there is less code to parse: only the types of exported constructs..ts
files require type checking to extract the types.Andrew Branch has benchmarked the difference and type-checking the d.ts
version of a dependency took 58% of type-checking the .ts
version.
.d.ts
files are more stable than .ts
files. This is an example given by Daniel Rosenwasser: “when TypeScript introduced the satisfies
operator, library authors were able to use it without worrying about consumers because expression-level syntax never appears in .d.ts
files.”
Source:
.ts
files.Node.js does not support TypeScript in packages, JSR supports publishing packages with .ts
files. Both have pros and cons. A few thoughts:
.d.ts
is an interesting point in its favor..ts
dependency could be sped up if it adheres to the constraints of isolated declarations: Compared to a .d.ts
dependency, there would still be more parsing. But no semantic analysis would be needed because the .d.ts
information is syntactically embedded inside the .ts
file..ts
on demand to .js
and .d.ts
has become fast, thanks to type stripping and isolated declarations. If that is done, it should probably happen on the server. Otherwise, local package manager binaries would become outdated too quickly.ES Module Shims brings new ESM features to older browsers. It lets us run TypeScript in browsers – via on-demand type stripping:
<script type="module" src="app.ts"></script>
It’s interesting how ES Module Shims handles MIME types (source):
video/mp2t
for files with the filename extension .ts
. Therefore, ES Module Shims does not check the mime type if a file has the filename extension .ts
or .mts
. For all other files, MIME types are required and the mime type application/typescript
is supported.A proposal to add optional type annotations to JavaScript (by Gil Tayar, Daniel Rosenwasser, Romulo Cintra, Rob Palmer) is currently at stage 1.
The core idea of the proposal is:
Most server-side runtimes already directly support TypeScript, so what’s a better solution for browsers: type-stripped TypeScript or JavaScript with optional type annotations?
With type stripping – will JSX become less popular? There are alternatives that use tagged templates – e.g.:
Type stripping does not allow enums either. Two alternatives are currently on the horizon:
enum Color {
Red = Symbol('Red'),
Green = Symbol('Green'),
Blue = Symbol('Blue'),
}
const Color: enum = {
Red: Symbol('Red'),
Green: Symbol('Green'),
Blue: Symbol('Blue'),
};
isolatedDeclarations
: generating .d.ts
files more efficiently” in “Exploring TypeScript”