TypeScript for JavaScript Programmers
TypeScript stands in an unusual relationship to JavaScript. TypeScript offers all of JavaScript’s features, and an additional layer on top of these: TypeScript’s type system.
For example, JavaScript provides language primitives like string and number , but it doesn’t check that you’ve consistently assigned these. TypeScript does.
This means that your existing working JavaScript code is also TypeScript code. The main benefit of TypeScript is that it can highlight unexpected behavior in your code, lowering the chance of bugs.
This tutorial provides a brief overview of TypeScript, focusing on its type system.
TypeScript knows the JavaScript language and will generate types for you in many cases. For example in creating a variable and assigning it to a particular value, TypeScript will use the value as its type.
By understanding how JavaScript works, TypeScript can build a type-system that accepts JavaScript code but has types. This offers a type-system without needing to add extra characters to make types explicit in your code. That’s how TypeScript knows that helloWorld is a string in the above example.
You may have written JavaScript in Visual Studio Code, and had editor auto-completion. Visual Studio Code uses TypeScript under the hood to make it easier to work with JavaScript.
You can use a wide variety of design patterns in JavaScript. However, some design patterns make it difficult for types to be inferred automatically (for example, patterns that use dynamic programming). To cover these cases, TypeScript supports an extension of the JavaScript language, which offers places for you to tell TypeScript what the types should be.
For example, to create an object with an inferred type which includes name: string and id: number , you can write:
You can explicitly describe this object’s shape using an interface declaration:
You can then declare that a JavaScript object conforms to the shape of your new interface by using syntax like : TypeName after a variable declaration:
If you provide an object that doesn’t match the interface you have provided, TypeScript will warn you:
Since JavaScript supports classes and object-oriented programming, so does TypeScript. You can use an interface declaration with classes:
You can use interfaces to annotate parameters and return values to functions:
There is already a small set of primitive types available in JavaScript: boolean , bigint , null , number , string , symbol , and undefined , which you can use in an interface. TypeScript extends this list with a few more, such as any (allow anything), unknown (ensure someone using this type declares what the type is), never (it’s not possible that this type could happen), and void (a function which returns undefined or has no return value).
You’ll see that there are two syntaxes for building types: Interfaces and Types. You should prefer interface . Use type when you need specific features.
With TypeScript, you can create complex types by combining simple ones. There are two popular ways to do so: with unions, and with generics.
With a union, you can declare that a type could be one of many types. For example, you can describe a boolean type as being either true or false :
Note: If you hover over MyBool above, you’ll see that it is classed as boolean . That’s a property of the Structural Type System. More on this below.
A popular use-case for union types is to describe the set of string or number literals that a value is allowed to be:
Unions provide a way to handle different types too. For example, you may have a function that takes an array or a string :
To learn the type of a variable, use typeof :
Type | Predicate |
---|---|
string | typeof s === «string» |
number | typeof n === «number» |
boolean | typeof b === «boolean» |
undefined | typeof undefined === «undefined» |
function | typeof f === «function» |
array | Array.isArray(a) |
For example, you can make a function return different values depending on whether it is passed a string or an array:
Generics provide variables to types. A common example is an array. An array without generics could contain anything. An array with generics can describe the values that the array contains.
ts
type StringArray = Arraystring>;type NumberArray = Arraynumber>;type ObjectWithNameArray = Array< name: string >>;
You can declare your own types that use generics:
One of TypeScript’s core principles is that type checking focuses on the shape that values have. This is sometimes called “duck typing” or “structural typing”.
In a structural type system, if two objects have the same shape, they are considered to be of the same type.
The point variable is never declared to be a Point type. However, TypeScript compares the shape of point to the shape of Point in the type-check. They have the same shape, so the code passes.
The shape-matching only requires a subset of the object’s fields to match.
There is no difference between how classes and objects conform to shapes:
If the object or class has all the required properties, TypeScript will say they match, regardless of the implementation details.
This was a brief overview of the syntax and tools used in everyday TypeScript. From here, you can:
The TypeScript docs are an open source project. Help us improve these pages by sending a Pull Request ❤
JS Projects Utilizing TypeScript
The type system in TypeScript has different levels of strictness when working with a codebase:
- A type-system based only on inference with JavaScript code
- Incremental typing in JavaScript via JSDoc
- Using // @ts-check in a JavaScript file
- TypeScript code
- TypeScript with strict enabled
Each step represents a move towards a safer type-system, but not every project needs that level of verification.
TypeScript with JavaScript
This is when you use an editor which uses TypeScript to provide tooling like auto-complete, jump to symbol and refactoring tools like rename. The homepage has a list of editors which have TypeScript plugins.
Providing Type Hints in JS via JSDoc
In a .js file, types can often be inferred. When types can’t be inferred, they can be specified using JSDoc syntax.
JSDoc annotations come before a declaration will be used to set the type of that declaration. For example:
You can find the full list of supported JSDoc patterns in JSDoc Supported Types.
The last line of the previous code sample would raise an error in TypeScript, but it doesn’t by default in a JS project. To enable errors in your JavaScript files add: // @ts-check to the first line in your .js files to have TypeScript raise it as an error.
If you have a lot of JavaScript files you want to add errors to then you can switch to using a jsconfig.json . You can skip checking some files by adding a // @ts-nocheck comment to files.
TypeScript may offer you errors which you disagree with, in those cases you can ignore errors on specific lines by adding // @ts-ignore or // @ts-expect-error on the preceding line.
To learn more about how JavaScript is interpreted by TypeScript read How TS Type Checks JS
JS Projects Utilizing TypeScript
The type system in TypeScript has different levels of strictness when working with a codebase:
- A type-system based only on inference with JavaScript code
- Incremental typing in JavaScript via JSDoc
- Using // @ts-check in a JavaScript file
- TypeScript code
- TypeScript with strict enabled
Each step represents a move towards a safer type-system, but not every project needs that level of verification.
TypeScript with JavaScript
This is when you use an editor which uses TypeScript to provide tooling like auto-complete, jump to symbol and refactoring tools like rename. The homepage has a list of editors which have TypeScript plugins.
Providing Type Hints in JS via JSDoc
In a .js file, types can often be inferred. When types can’t be inferred, they can be specified using JSDoc syntax.
JSDoc annotations come before a declaration will be used to set the type of that declaration. For example:
You can find the full list of supported JSDoc patterns in JSDoc Supported Types.
The last line of the previous code sample would raise an error in TypeScript, but it doesn’t by default in a JS project. To enable errors in your JavaScript files add: // @ts-check to the first line in your .js files to have TypeScript raise it as an error.
If you have a lot of JavaScript files you want to add errors to then you can switch to using a jsconfig.json . You can skip checking some files by adding a // @ts-nocheck comment to files.
TypeScript may offer you errors which you disagree with, in those cases you can ignore errors on specific lines by adding // @ts-ignore or // @ts-expect-error on the preceding line.
To learn more about how JavaScript is interpreted by TypeScript read How TS Type Checks JS