1/ Everything is a Type
The foundation of TypeScript is that everything — absolutely every variable, constant, or object — is a type.
You will always be declaring types, and chasing down the type declaration of your variables, constants, and objects to understand how to work with them.
Declaring your types means you are telling the TypeScript compiler “I know what type of thing this variable is.” Unlike duck-typed and loosely-typed languages, a strongly typed language like TypeScript means you should always have confidence that a variable is what it says it is.
Indeed, In the case when you don’t know what an input might be, TypeScript has mechanisms for that as well. Except in the case where you are receiving data from external inputs, you can be assured that the TypeScript compiler means this is true (More on that in section 4).
Variable, Constant, and Object Declaration
const), but has two extra elements: a colon (
:) and a type declaration.
var foo : string;
foo (in local-scope) and tell the TypeScript compiler it is a String. The only exception is when assigning a variable to a literal, TypeScript can infer the type declaration for you.
foo = "Hello world";
Here, TypeScript already knows that
"Hello world" is a string (it knows this because it is surrounded by quotation marks. We call this a string literal.) Likewise, since we are assigning the string literal directly onto the variable
This assumes you have the
noImplicitAny setting set to true (see below), which is strongly recommended.
Function Parameter Declaration
All functions which take inputs in TypeScript (arity) have declared types. Hence, that means that when you declare a function you will also be declaring types for the inputs (variables) passed to the function. This is referred to as “function type declaration” and looks like this:
Return Value Declaration
All functions which return a value (if they return a value), that has a declared type return value. Indeed, this means that when you are working with TypeScript, the compiler is checking your type declarations. How does it do this?
Well, it does this using a Typescript compiler, which we will configure in the next section. It can do this because of two things: (1) An integration with your IDE (VSCode, WebStorm, or Rubymine) or powerful shell editor like vim means that when the coding tool itself runs, and (2) the settings specified in your Typescript config file
The code you write is always being checked in the background for TypeScript problems, which are nearly always type declaration mismatches.
2/ Getting TypeScript
To install tsc for the first time (the command line tool used to work with TypeScript), you must first install it using Yarn or NPM.
If you use yarn, run:
yarn global add tsc
If you use npm, run:
npm install -g tsc
Alternatively, you can also install it globally using Homebrew, like so:
brew install typescript
Check to make sure you have the
tsc command install using
If you see the path to the
tsc command, you are OK to continue. If you see “
tsc not found” you do not have the command correctly installed.
4/ TypeScript Config
Let’s make our first TypeScript experiment and learn how to set up our TypeScript config. The Typescript config is the all-important configuration file that tells TypeScript exactly what to do. Since TypeScript has several different options, this file is very important to understand. In this crash course, we will cover only the first few and most important options for setting up new projects.
Create a new empty project using
cd HelloTS to change directory into that directory.
tsc --noImplicitAny --init to create a new basic
Let’s take a look at our new file in our code editor:
Notice that nearly every option is commented out (shown as light grey), which means it doesn’t apply.
The first option not commented out is the
Next is the
module setting, which specifies which style of module declaration to use: AMD or commonjs.
Next is the
strict mode setting, which we have set here to true. By default, if you have strict mode enabled, all of the “strict” settings will also be enabled (even if they are commented out in the
We haven’t actually learned what the “any” type is at all (more on that in Lesson 6), but this tells TypeScript that all variables, constants, and objects must have known Types (that is, we must declare them or let TypeScript infer them when we write our code.) This is the fundamental paradigm of TypeScript itself and how we introduced TypeScript above, so that’s why it is presented here as the default setting.
Should I use strict mode in TypeScript or not?
If you just start a new project using strict mode in TypeScript is strongly recommended. It will help you to avoid errors, typos, and mistakes in your code.
Strict mode constricts you in how you can write your code.
If you want to have just some of the strict mode settings, you can opt-in parameter by parameter. (For example, if you have an existing codebase you want to convert over into TypeScript.)
You probably won’t be able to set parameter strict to true in an existing project. But you can set some strict mode parameters to gradually rewrite your codebase using strict mode rules.
For example, you can set the parameter noImplicitAny to true and rewrite your code to one that is following this rule (you should write a type of parameters in every function).
5/ Compiled vs. Executed
One of the key things to understand about TypeScript is that type checking happens when your code is compiled, not necessarily when it is executed.
The only time a static type is checked in TypeScript is during compilation.
This means that you aren’t really guarding against the kind of invalid input you may encounter coming from an external source.
By default, TypeScript does not verify types at runtime. This avoids runtime overhead and also aggressively optimizes runtime performance.
So how do you enforce a thing is the correct type at runtime?
- TypeScript type guards: Type guards restrict the scope of variable types through conditional blocks and determine the type of variable to expect during code execution
- Validation libraries: These libraries provide ready-made boilerplate code, methods, and interfaces to perform schema validation for your variable types
- JSON schemas: The popular data interchange format for fast, easy, lightweight, and quick data transfers as well as conversion for the different entities to communicate.
- Manual checks: Manually maintaining the set of rules and applying it on a specific language to validate the types of data values — this is a cumbersome way of single-handedly managing rules with no other runtime type checking approach or library used, and eventually creates an unstable system.