typescript function and object and advanced types

Function


It's better practice to declare the return data type even though the compiler can infer it.

function calc(input: number): number{

  return input * 2

}


Another way to declare a function is the arrow way

let add: (x: number, y: number) => number; 


Optional parameter. The ? indicates optional, but if not supplied, it's undefined, cant use it.

So the optinal parameter needs to handled with e.g. the or || operator, which means if not supplied, it's 10 here.

function calc(input: number, rate?:number): number{

  let r = (rate || 10)

  return input * 2 * r

}

A better way for optional parameter is just suppling a default value, this is same as in python.

function calc2(input: number, rate:number=10): number{

return input * 2 * rate

}


Overload

similar to languages like java, it can overload a function. Note it has to declare only the different types of functions without implementation. At the end, an implementation with the any data type.

function abc(i: number): number;

function abc(i: string): string;

function abc(i: any): any{

  return i

}


Object

A way to define object is using the {} and list all the attributes and methods. 

When assigning a value, it has to give value for each attribute and method

let employee: {

  id: number,

  name: string,

  say_hello: (input: string) => string,

} = {id: 1, 

     name: 'hey',

     say_hello: (input: string) => {console.log(input); 

                                    return input;}

    } 

let output = employee.say_hello('good day')


It not good repeat the employee definition again and again, then just decalre an Employee type

type Employee = {

  id: number,

  name: string,

  say_hello: (input: string) => string,

} ;

let employee2: Employee = {

     id: 1, 

     name: 'hey',

     say_hello: (input: string) => {console.log(input); 

                                    return input;}

    } ;

employee2.say_hello('good day'); 



union of types

This allows the parameter to take in different types of data, and leave it to the funciton to handle it separately.

Note the typeof helps to check the type of the parameter.

function calc3(num:number | string): number{

  if (typeof num == 'number')

      return num * 2

  else

      return parseInt(num) * 2

}

console.log(calc3(1))

console.log(calc3('1kg'))


intersection of types

Declare a variable as multiple types at the same type

let a: number & string 

Above is impossible for premitive types because it cant be both number and string at the same time.

However, for object type, it can make a lot of sense

type Moveable = {

  move: () => void;

}

type Printable = {

  print: () => void

}

type CustomType = Moveable & Printable //this type can be both moveable and printable

let ct: CustomType = {

  move: ()=>{console.log('moving')},

  print: ()=>{console.log('printing')},

}

ct.move()

ct.print()


literal types

Sometimes one wants to limit the values to a certain list, e.g. rank can only be 1, 10 or 20, cant be anything else.

Then you can declare a varialbe or a type as 1 | 10 | 20. This is a bit similiar to enum but only a list of acceptable values.

type Ranks = 1 | 10 | 20;

let rank: Ranks = 20


allow null value in function parameter

This allows a value or null if no value to be passed into a function. Sometimes there are legitimate reasons why a null value is passed in.

function show(msg: string | null | undefined): void{

  if (msg)

    console.log(msg)

  else

    console.log('nothing to show')

}


optional property access operator

In many languages, calling the method/propery of a null object cause errors. Usually it needs a check if the object is null, and only calls the property or method if the object is not null.  E.g. The function below can return null value if id=0. Then it has to check if its null or not before console log.

type Customer = {

  name: string,

}

function getCustomer(id: number): Customer | null {

  return id===0 ? null : {name: 'hello'}

}

let cust = getCustomer(0)

if (cust !== null)

  console.log(cust.name)

else

  console.log('null name')

Above is a bit too length. A better way in TYpescript is to use the ? as optional access to property only if it is not null, which removes the need for if--else--. When it is null, the optional propery access returns 'undefined'

cust = getCustomer(0)

console.log(cust?.name)


optinoal function call

Similar concept can apply to function call as well. Below is a normal function call.

let print_msg: Function = (msg: string) => console.log(msg);

print_msg('hello')

But if the function has not be defined yet, the ? helps to not run it.

let print_msg2: any = null

print_msg2?.('hello')