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": ["**/*"]
}