Typescript notes
Typescript notes
Official Typescript site for downloads and documentation
Table of Contents
- Installing and initializing a project
- Useful commands
- Variables
- Functions
- type
- Arrays
- Union
- Tuples
- Enums
- Interfaces
- Classes, getters and setters
- Class implementing an interface
- Abstract class
- Generics
Installing and initializing a project
Typescript does “Static Checking”
npm install typescript
npx tsc
Then convert .ts to .js with tsc myfile.ts
and run it with node cmyfile.js
Usual steps to start a common Typescript project in an empty folder
# To initialize a folder with Typescript (creates a `tsconfig.json` file)
tsc --init
# Create the `package.json` file.
npm init
# Create the usual folders (src for ts files and dist for js files)
mkdir src dist
# Create first ts file
touch ./src/index.ts
Then create a index.html
file pointing to the compiled ./dist/index.js
.
Type !
in an empty index.html
file and enter the script in the body:
<body>
<script src="./dist/index.js"></script>
</body>
Useful commands
Run tsc in watch mode.
tsc --watch
Install the Live Server extension.
Variables
Javascript just has numbers (not int or floats for example)
let variablename: type = value
let text21 = "Hello World"; //This will detect its a string and make it type script. Not like in Javascript
// Adding this line makes the file a module instead of a script
export {}
In variables the type can be optional to enter if Typescript can guess it, but in functions I should normally always enter it
Functions
function name(num: number = 0) : boolean { //Function will return a boolean
if (num > 0) {
return true
}
}
Or arrow function:
let loginUser = (name: string, email: string, isPaid: boolean = false): boolean => {
return true
}
Its good practice to specify void
if a function is meant to return anything, so no one tries to return something with it.
We use never
when the function trows an exception or terminates execution of the program
For example:
function consoleError(errormessage: string): void {
console.log(errormessage);
}
function handletError(errormessage: string): never {
throw new Error(errmsg);
}
Functions that return an object
function createCourse():{}{
return myobject;
}
function createCourse():{name: string, price: number}{
return {name: "typescript", price: 1000};
}
type
type car = {
readonly make: string; //mark this property as readonly
model: string;
year: number;
color?: string; //mark this property as optional
}
//create a new type that extends car and adds a driver property
type carwithdriver = car & {
driver: string;
}
function createCar(mycar: car):car {
console.log(mycar.make + " " + mycar.model + " " + mycar.year);
return mycar;
}
let carone : car = {
make: "Volvo",
model: "XC60",
year: 2017
}
Arrays
const myarray: number[] = [1,2,3,4,5,6,7,8,9,10];
//Another format of doing the same is
const myarray2: Array<number> = [1,2,3,4,5,6,7,8,9,10];
//Double all numbers in myarray
const doubleArray = myarray.map((num) => {
return num * 2;
});
//print out all numbers in myarray in same line
//and go to next line after printing all numbers
function printArray() {
myarray.map((num) => {
process.stdout.write(num + " ");
});
console.log();
}
printArray();
//Add 11 to the end ºof myarray
myarray.push(11);
//print out all numbers in myarray
printArray();
//array of arrays
const myimage: number[][] = [
[255,255,255],
[255,0,0],
];
export {}
Union
Union use case in variables
let badge: number | string = 100;
badge = "100 Club";
//Will only allow values of "gold", "silver" or "bronze"
let metal: "gold" | "silver" | "bronze" = "gold";
Union case with types
type User = {
name: string;
id: number;
}
type Admin = {
username: string;
id: number;
}
let alejandro: User | Admin = {name: "Alejandro", id: 1};
//I can change a property that was not defined in User but is in Admin
alejandro = {username: "alejandro", id: 1};
Union case with functions
function getId(id: number | string) {
if(typeof id === "string") {
return id.toUpperCase();
}
console.log('DB id is: ' + id);');
}
Union case with arrays
const myArrayWithNumbersOrStrings: (number | string)[] = [1,2,"text"];
const myArrayOfNumbersOrStrings: string[] | number[] = [1,2,3];
type MyArr = number[] | string[];
Tuples
Official definition: A tuple type is another sort of Array type that knows exactly how many elements it contains, and exactly which types it contains at specific positions
let position: [number, number] = [255,255];
type Person = [number, string];
let myPerson: Person = [1, "Alejandro"];
myPerson[0] = 2;
Enums
To define a set of named constants.
enum Manufacturer2 {
Honda = 10, //You can optionally set the value of an enum
Volvo,
BMW
}
let myChoice2 = Manufacturer2.Volvo
console.log(myChoice); //This is output as 11.
Interfaces
Note: Key difference between interface
and type
is that interface
can be re-opened to add new properties
interface Persona {
readonly preId: number,
email: string,
Name: string,
age?: number
startProcess():string, //Can also be typed as: startProcess: () => string;
getCoupon(name: string, value: number): number
}
//you can also extend interfaces
interface Persona {
city?: string
}
interface SuperPersona extends Persona {
superpower: string
}
let firstUser: Persona = {
preId: 1,
email: "hello@hello.com",
Name: "John",
startProcess() {
console.log("Starting process");
return new Date().toISOString(); //return current date in string format
},
getCoupon: (name: "Golden", value: 10) => {
return 10;
}
}
Classes, getters and setters
Getters and setters can be use to access private properties that are usually not available out of the class or to add a bit more logic when reading or writing the data.
class User {
private counter: number = 0;
protected key: string = "A1234" //can be accessed by child class
constructor(
private email: string,
private name: string
) {}
get getEmail(): string {
return this.email;
}
get getcounter(): number {
return this.counter;
}
set setcounter(value: number) {
if (value < 0) {
throw new Error("Counter must be greater than 0")
}
this.counter = value;
}
}
const someone = new User("aa", "bb");
Class implementing an interface
A class can implement an interface to assure that it follows the same format
class myclass implements myinterface {
constructor(
public field1: string
public field2: number
){}
}
Abstract class
You cannot create an object from an abstract class. We usually use them to extend them instead.
abstract class Car {
constructor(
protected model: string,
protected year: number
) {}
abstract getPrice(): void;
getAgeInYears(): number
{
return new Date().getFullYear() - this.year;
};
}
class Volvo extends Car {
constructor(
protected model: string,
protected year: number,
protected securitylevel: number
) {
super(model, year); //super() is required to have all required values of the abstract class
}
getPrice(): void {
console.log("Price is 10000");
}
getAgeInYears(): number {
return super.getAgeInYears();
}
}
Generics
//This function could for example get a Number and return a String
function example1(val:any):any {
return val
}
//This function accepts multiple types but will always return the same type that was entered
function example2<Type>(val: Type): Type {
return val
}
//Another more common way to write the same thing is using a letter (can be any letter or text, like 'T' or anything else):
function example3<T>(val: T): T {
return val
}
I can also use generics to use a personalized type
function example3<T>(val: T): T {
return val
}
interface Table {
manufacturer: string,
seats: number
}
example3<Table>({manufacturer: "Make1", seats: 4})