Typescript's Static Typing System
Predicting what the code will do before it runs
Typescript's static typing system helps us catch errors during development. When we run our code, the way that our JavaScript runtime chooses what to do is by figuring out the type of the value.
For some values, such as the primitives string and number, we can identify their type at runtime using the typeof operator. But for other things like functions, there's no corresponding runtime mechanism to identify their types.
In the example below, the JS interpreter access a property called toLowerCase, and then calls it. In the next line, it tries to call message directly.
Ex
const message = "Hello World"
message.toLowerCase();
//calling mesage
message();
But assuming we don't know the value of message, we can't reliably say what results we'll get from trying to run any of this code. The behaviour of each operation depends entirely on what value we have in 'message', and on whether 'message' is callable.
If we try to run message.toLowerCase(), we'll get the same string only in lower-case.
Now the next line calls message(), and the code fails with an exception: 'TypeError: message is not a function'.
But predicting what the code will do before it runs isn't always as straight forward as shown here above.
Consider the following example
function fn(x) {
return x.flip();
}
This function will only work, if given an object with a callable flip method, but JS doesn't have a static type system so it can't tell us about most type errors before we run the code. The only type-checking JS provides is dynamic typing - running the code to see what happens.
Seen in this way, a type is the concept of describing which values can be passed to a function fn, and Typescript as a type-checker does that for us.
Static type systems describe the shapes and behaviours of what our values will be when we run our programs. So that when we run this first sample with Typescript will give us an error message before we run the code.
const message = "Hello World";
message();
// This expression is not callable.
// Type 'String' has no call signatures.
Javascript provides language primitives like 'string' and 'number', but it doesn't check that you've consistently assigned these. Typescript on the other hand does.
In this example, Typescript is able to highlight unexpected behaviour in your code when we call a property that doesn't exist on an object, and unlike the response we get from the JS interpreter, which isn't so obvious
const user = {
name: "Tom",
age: 32,
};
user.location;
// > returns undefined
In Typescript, the same code produces an error about location not being defined.
interface User {
name: string;
age: number;
}
const user: User = {
name: "Tom",
age: 32,
};
user.location;
// > Property 'location' does not exist on type '{ name: string; age: number; }'.