TypeScript
TypeScript is a superset of JavaScript. This means it inherits everything JavaScript can do. If you can make a program with JavaScript, you can also make it with TypeScript. TypeScript compiles into plain JavaScript, since a browser such as V8 can’t read TypeScript, you must compile it into JavaScript first.
Why use it??
It has Static Type Checking! JavaScript is a dynamically typed language. You might think typing has something to do with using a keyboard, but you would be very wrong. The difference between Static Type Checking and Dynamic Type checking is when the Types are checked. Types refers to what type something is, a variable could be a string, number, null, undefined, boolean, symbol, or object.
- Dynamically Typed languages check types during code execution
- Statically Typed languages check types before run-time
And???
JavaScript, at run time, uses something called “type coercion” if it needs, for example, to add a variable with the value of ‘10’ (a string) with another variable with the value of 12 (a number). It converts the string of 10 into a number, and the result is 22. As you can see, this might cause problems with incorrect inputs in your program. When you write JavaScript, you can declare variables without declaring what type it is.
TypeScript to the rescue!
TypeScript lets you use Static Type Checking in your JavaScript code, and it will throw an error before run-time if there is an issue (such as trying to add a string and boolean together). TypeScript files, with a .TS extension, let you declare types in your code as an option. You don’t have to declare types, any JavaScript is valid TypeScript code. Here is a TypeScript code example, you can see the type declared at the top.
let myString: string;
myString = "Hiiii";
console.log(myString);
After you compile the TypeScript file it returns a new file containing plain JavaScript:
var myString;
myString = "Hiiii";
console.log(myString);
What if you use a number instead of a string in your TypeScript file? In my VS code it instantly shows it as an error
let myString: string;
myString = 230;
console.log(myString);
If you compile the above code, the console will spit out an error at you but it will still compile into JavaScript:
var myString;
myString = 230;
console.log(myString);
You can set primitive types easily:
let myString: string;
let myNum: number;
let myBol: boolean;
let myString2: string;
let myVar: any;
myString = "hi";
myNum = 55;
myBol = true;
myString2 = "hello".slice(0, 2);
myVar = 5;
console.log(myString);
console.log(myNum);
console.log(myBol);
console.log(myString2);
console.log(myVar);
For arrays it is also very simple:
Another way to define arrays in TypeScript:
let strArr3: Array<string>;
let boolArr2: Array<boolean>;
let numArr2: Array<number>;
strArr3 = ["blue", "blue"];
numArr2 = [11, 99, 100000];
boolArr2 = [true, false, false]
Tuples
JavaScript does not have Tuples defined in the language, but TypeScript does. A tuple is just an array with a predefined number of elements, and you can define what type each element in the array is:
let strNumTuple: [string, number];
strNumTuple = ['hello', 100]
Null, Undefined
Both of these can be set as a type, void for either null or undefined. Or set them to null or undefined specifically.
let myVoid: void = null;
let myVoid2: void = undefined;
let myNull: null = null;
let myUndefined: undefined = undefined
Functions
You can set types for parameters and the type the function must return. This will show in your code editor if you try to call a function with an incorrect parameter type. Helps avoid mistakes! You can set a parameter to any, and to return a number.
function getSum(num1: number, num2: number): number {
return num1 + num2;
}
function getSum2(num1: number, num2: any): number {
if(typeof num1 == 'string') {
num1= parseInt(num1)
}
if(typeof num2 == "string") {
num2 = parseInt(num2)
}
return num1 + num2;
}
console.log(getSum2(1, '4'));
console.log(getSum(1, 4));
Here we can make parameters optional using ’?‘:
function getName(firstName: string, lastName: string): string {
return firstName + " " + lastName;
}
console.log(getName("John", "Doe"));
function getName2(firstName: string, lastName?: string): string {
if(lastName == 'undefined') {
return firstName
}
return firstName + " " + lastName;
}
console.log(getName2("John"));
You can make a function return void:
function myVoid6():void{
return;
}
Interfaces:
Here is something new! TypeScript has two ways of defining the structure of your object, with Types or Interfaces.
When to use each?? An interface can be easily extended using the extend keyword, and used to enforce types on variables in your code base. It can be used on classes as well, using the implements keyword. Below you can see a basic interface versus declaring the types directly in the function parameters, much cleaner and easier to read.
function showTodo(todo: {title: string, text: string}) {
console.log(todo.title+": "+todo.text);
}
let myTodo = {title:'Trash', text:'Take it outtt'}
showTodo(myTodo);
interface Todo2 {
title: string,
text: string,
}
function showTodo2(todo: Todo2) {
console.log(todo.title+": "+todo.text);
}
let myTodo2 = {title:'Trash', text:'Take it outtt'}
showTodo(myTodo2);
Interfaces vs Types
WHY??! Technically it does not matter, though there are some differences but over time they have gotten closer and closer. Interfaces are geared towards defining objects, classes, and functions. Interfaces were originally made to describe objects. Below is a nice simple example of an interface and a variable with an object assigned to it, that is type checked using the interface. There i also a Class and function example using interfaces.
interface Person {
name: string;
hungry: boolean;
}
const me: Person = {
name: 'Harry',
hungry: false,
}
class Harry implements Person {
name: string;
hungry: boolean;
}
interface Greeting {
(name: string): string;
}
const myGreeting: Greeting = (name) => "Hello!";
Interfaces can be extended:
A unique feature of interfaces is that they can be extended. See the photo below and note the error, underlined in red because it is missing the “youtuber” property in the object.
Declaration Merging:
Another unique interface feature is deceleration merging, you create an interface with a name, and later create an interface using the exact same name again. Here we see the error thrown because the “me” const wants the properties of both interfaces, not just one. It merges them together.
Summary of Interface unique properties:
- Interfaces are geared towards objects, classes and functions
- Interfaces can be extended
- Interfaces have “Declaration Merging”
Type Alias:
Typescript can be used with the type keyword to create aliases. type hungry = boolean;
You can type alias functions as well. type Greeting = (name: string) => string;
These are used as way to save having to retype type declarations that you would otherwise have to do inline.
Types are a bit different. const harry: Hungry = true;
works. const harry: Hungry = "true";
will throw and error message, saying Type '"true"' is not assignable to type 'boolean'
instead of saying type Hungry is not assignable, because it is using a type alias. This is called opaque types, and if TypeScript had it, would show “Hungry is not assignable” instead. Apparently TypeScript might add this in the future.