Get Started with Typescript

1 Get Started with Typescript

Any large and good apps written in Javascript will be eventually written in Typescript.

1-1 Types of Languages

  • Dynamically Typed Language

    • Type check will be done at runtime
    • No need to assign data type to variables, very flexible
    • e.g. Python, Javascript etc.
    • Note Python has introduced the type hint
  • Statically Typed Language

    • Type check happens during the compile phase
    • Need to declare the data type for variables
    • e.g. C++, Java

1-2 What is Typescript

  • A Javascript superset
  • Javascript that scales
  • A Typed language
  • Supporting ES6 through ES10 even ESnext
  • Compatible with modern browsers, OS, servers
  • Open Source

1-3 Why use Typescript

  • Easy to understand
  • Easy to prevent errors
  • More efficient
  • Completely Compatible with JS
  • More and more popular frameworks are written in Typescript now
  • Cons
    • Learning curve
    • Additional dev costs in the near term

1-4 Install Typescript

  • Install Typescript
npm install -g typescript
  • Check version
tsc -v

Version 3.8.3
  • Install a certain version
npm i -g typescript@3.7.2

Check version again

Version 3.7.2

1-5 Hello World in Typescript

  • Create a file hello.ts
  • Edit the file
const hello = (name: string) => {
  return `hello ${name}`
}

hello('World')
  • Compile the file
tsc hello.ts

Then the system will generate a js file

var hello = function (name) {
    return "hello " + name;
};
hello('World');
  • Error during compiling
const hello = (name: string) => {
  return `hello ${name}`
}

hello('World')
hello(42)

System will report error if compiling

helloword.ts:6:7 - error TS2345: Argument of type '20' is not assignable to parameter of type 'string'.

6 hello(20)
        ~~
Found 1 error.

2 Data Type

2-1 Data types in Javascript

There are 7 primitive data types:
- Boolean
- Null
- Undefined
- Number
- BigInt (ES6)
- String
- Symbol (ES6)
And Object

2-2 Basic Data Types

Some basic data types:

let isDone: boolean = false

let age: number = 20
let binNumber: number = 0b1111

let firstN: string = "Isaac"
let msg: string = `Hello ${firstN}, age is ${age}`

let udf: undefined = undefined
let n: null = null

note undefine and null are sub-type for number, string and boolean, we can define a number type undefined

Below is valid:

let myNum: number = undefined

2-3 any Type and uniTypes

  • For unknown types, we can use any
  • Be cautious on any
let notSure: any = 4
notSure = "maybe it is a string"
notSure = true
  • Unitypes: could be a combined types
let numberOrString: number | string = 234
numberOrString = "a string"

// below will be an error
// numberOrString = true

2-4 Array and Tuple

  • Start with an array example
  • Is limited only to the type defined
let arrOfNum: number[] = [1,2,3,4]
arrOfNum.push(5)
  • arraylike objects in javascript
  • In javascript there are some data types similar to arrays but are not actually arrays
  • For example, arguments after defining a function
function test(){
  // arguments is similar to an array
  console.log(arguments)
  console.log(arguments.length)
}
  • Tuples can contain different types
let user: [string, number] = ["this is a string", 20]

2-5 Interface

  • Describe the object shape
  • Class Abstraction
  • Duck Typing
interface Person {
  name: string;
  age: number;
}

let isaac: Person = {
  name: "Isaac",
  age: 20
}
  • Optional attribute
interface Person {
  name: string;
  // now age is optional
  age?: number;
}

let isaac: Person = {
  name: "Isaac",
}
  • ReadOnly
interface Person {
  readonly id: number;
  name: string;
  age?: number;
}

let isaac: Person = {
  id: 1234,
  name: "Isaac",
}

// cannot change id, below will report error
// isaac.id = 3049

The difference between read-only and const

  • read-only is applied to the attribute
  • const is applied to the variable

2-6 Function

  • Fixed arguments
    function add(x:number, y:number):number {
    return x + y
    }
    

let result = add(2,3)


- Optional arguments

```typescript
function add(x:number, y:number, z?:number):number {
  if (typeof z === "number"){
    return x + y + z
  }
  else {
    return x + y
  }
}

let result = add(2,3, 5)
let result2 = add(3,5)
  • Optional arguments cannot be placed after required arguments
// below will report error
function add(x:number, z?:number, y:number):number {
  if (typeof z === "number"){
    return x + y + z
  }
  else {
    return x + y
  }
}
  • Function Expression
const add = function add(x:number, y:number, z?:number):number {
              if (typeof z === "number"){
                return x + y + z
              }
              else {
                return x + y
              }
            }

// below will report error
const add2: string = add

// correct
const add3:(x:number, y:number, z?:number) => number = add
  • In the example above, add3 was automatically determined the type based on TS type inference

2-7 Class One

  • Class defines the abstract attributes
  • Object: an instance of class
  • Four Principles of OOP:
    • Encapsulation: only expose interfaces
    • Inheritance: child class inherits parent class attributes, potentially with their own attributes
    • Abstraction: abstract attributes
    • Polymorphism: Different inherited classes might have different implementations for the same method
class Animal {
  name: string;
  constructor(name:string) {
    this.name = name
  }
  run(){
    return `${this.name} is running`
  }
}

const python = new Animal("three")

console.log(python.run());

class Dog extends Animal {
  bark(){
    return `${this.name} is barking`
  }
}

const lasse = new Dog("lasse")
console.log(lasse.run());
console.log(lasse.bark());

class Cat extends Animal {
  constructor(name) {
    super(name);
    console.log(this.name);
  }
  run(){
    return `Cat ` + super.run()
  }
}

const cat = new Cat("Garfield")

console.log(cat.run());

2-8 Class Two

  • There are three types of attributes

    • public
    • private
    • protected
  • public: we can change the attribute and

class Animal {
  public name: string;
  constructor(name:string) {
    this.name = name
  }
  run(){
    return `${this.name} is running`
  }
}

const python = new Animal("three")

console.log(python.run());
console.log(python.name)
python.name = "3.8"
console.log(python.name)
  • private: for some attributes or methods inaccessible from the outsiders, including child class
class Animal {
  private name: string;
  constructor(name:string) {
    this.name = name
  }
  run(){
    return `${this.name} is running`
  }
}
  • protected: child class can access the protected attributes or methods
class Animal {
  protected name: string;
  constructor(name:string) {
    this.name = name
  }
  run(){
    return `${this.name} is running`
  }
}
  • readonly: can only read but not edit

    class Animal {
    readonly name: string;
    constructor(name:string) {
      this.name = name
    }
    run(){
      return `${this.name} is running`
    }
    }
  • static attributes and methods: can be accessed without instantiation

    class Animal2 {
    readonly name: string;
    static categories: string[] = ["mammal", "bird", "others"]
    static isAnimal(a) {
      return a instanceof Animal2
    }
    constructor(name:string) {
      this.name = name
    }
    run(){
      return `${this.name} is running`
    }
    }
    

const snake = new Animal2(“lily”)

console.log(Animal2.categories)
console.log(Animal2.isAnimal(cat))
console.log(Animal2.isAnimal(snake))


## 2-9 Interface and Implements

- Use interface and implements to abstract class attributes and methods

```typescript

interface Radio {
  switchRadio(trigger: boolean): void;
}

interface Battery {
  checkBatteryStatus(): number;
}

interface RadioWithBattery extends Radio{
  checkBatteryStatus(): number;
}

class Car implements Radio{
  switchRadio(){

  }
}

class Cellphone implements Radio, Battery{
  switchRadio(){

  }

  checkBatteryStatus():number {
    return 0
  }
}

class Cellphone2 implements RadioWithBattery{
  switchRadio(){

  }

  checkBatteryStatus():number {
    return 0
  }
}

2-10 Enumerates

enum Direction {
  Up = 10,
  Down,
  Left,
  Right
}

console.log(Direction.Left)
console.log(Direction[2])

2-11 Generics One

  • Generics: don’t specify the data type when defining a function or interface
function echo<T>(arg:T):T {
  return arg
}

const res = echo("str")
  • Multiple values
function swap<T, U>(tuple:[T,U]):[U,T] {
  return [tuple[1], tuple[0]]
}

const result = swap([1, "string"])
console.log(result)

2-12 Generics Two

  • Restricted Generics

interface IWithLength {
  length: number,
}

function echoWithLength<T extends IWithLength>(arg: T): T {
  console.log(arg.length)
  return arg
}

const str = echoWithLength("string")
console.log(str);

const obj = echoWithLength({length: 10, name: "Isaac"})
console.log(obj);

2-13 Generics Three

  • Generics on Class
class Queue<T> {
  private data = [];
  enqueue(item: T){
    return this.data.push(item)
  }
  dequeue(): T {
    return this.data.shift()
  }
}

const queue = new Queue<number>()
queue.enqueue(1)
queue.enqueue(2)
console.log(queue.dequeue().toFixed())
console.log(queue.dequeue().toFixed())

const queue2 = new Queue<string>()
queue2.enqueue("str")
queue2.enqueue("num")
console.log(queue2.dequeue().length)
console.log(queue2.dequeue().length);
  • Generics on Interface
interface KeyPair<T, U> {
  key: T;
  value: U;
}

let kp1: KeyPair<string,number> = {key:"A", value:2}
let kp2: KeyPair<number,string> = {key: 1, value:"str"}

let arr:number[]=[1,2,3]
let arr2:Array<number> = [1,2,3]
  • Interface with function
interface IPlus {
  (a: number, b:number) : number
}
function plus(a:number, b:number) :number {
  return a + b
}

const res:IPlus = plus
  • Generic Interface with Function
interface IPlus<T> {
  (a: T, b:T) : T
}
function plus(a:number, b:number) :number {
  return a + b
}
function connect(a:string, b:string):string {
  return a + b
}
const res:IPlus<number> = plus
const res2:IPlus<string> = connect

console.log(res(9,8))
console.log(res2("hello", "world"))

2-14 Type aliases

  • to define a function
    function sum(x:number, y:number):number {
    return x + y
    }
    

const sum2: (x:number, y:number) => number = sum


- alternatively, can use type aliases

```typescript
function sum(x:number, y:number):number {
  return x + y
}

type PlusType = (x:number, y:number) => number

const sum2:PlusType = sum
  • join type
type NameResolver = () => string
type NameOrResolver = string | NameOrResolver
function getName(n:NameOrResolver):string {
  if (typeof n === "string") {
    return n
  } else {
    return n()
  }
}
  • type assertion
function getLength(input:number|string) :number {
  const str = input as String
  if(str.length){
    return str.length
  } else {
    const num = input as number
    return num.toString().length
  }
}

an easier way to write above

function getLength(input:string|number):number {
  if((<string>input).length){
    return (<string>input).length
  } else {
    return input.toString().length
  }
}

2-15 Declare File

  • Declare var to use 3rd party libraries
declare var jQuery: (selector: string) => any
  • Save the above in a .d.ts file, e.g. jQuery.d.ts

  • tsconfig file

{
  "include": ["**/*"]
}

   Reprint policy


《Get Started with Typescript》 by Isaac Zhou is licensed under a Creative Commons Attribution 4.0 International License
  TOC