Typescript

  • What is typescript?
  • History & Today
  • Why?
  • Basics
  • Typescript Utilities
  • Examples
  • Future

Javascript


							let a = 'a string'
							a = 5
							a = [1, 'two', {three: true}]
						

Typescript


								let a = 'a string' // a is a string now
								a = 5 // ❌
								a = [1, 'two', {three: true}] // ❌
							

TS Config


						npm i typescript
						tsc --init
					

General

  • target (ES2014, ..., ES2019, ESNEXT, ...)
  • module (commonjs, es2016, esnext, ...)
  • jsx
  • esModuleInterop
  • allowSyntheticDefaultImports
  • experimentalDecorators
  • emitDecoratorMetadata

Type Cheking

  • noImplicitAny
  • strictNullChecks
  • strictFunctionTypes
  • strictBindCallApply
  • strictPropertyInitialization
  • noImplicitThis
  • alwaysStrict
  • noImplicitReturns
  • noFallthroughCasesInSwitch

Production

  • noUnusedLocals
  • noUnusedParameters
  • removeComments

Basics

Simple types


						const a: string = 'a string'
						const b: number = 5
						const c: boolean = true
						const d: string[] = ['a', 'b', 'c']
						const e: number[] = [1, 2, 3]
					

Simple types


						const a = 'a string'
						const b = 5
						const c = true
						const d = ['a', 'b', 'c']
						const e = [1, 2, 3]
					

Types


						type StrinOrNumber = string | number
					

						type StringOrNumberOrBoolean = StringOrNumber | boolean
					

Modifiers


						const a?: string // string | undefined

						const obj = {
							a: string,
							b?: number,
						}

						funntion log(msg?: string) {}
					

						class {
							b!: string
						}

						obj!.one!.two!.three
					

Interfaces


						interface Pizza {
							slices: number
							round: boolean
							name: string
						}

						const pizza: Pizza = {
							slices: 4,
							round: true,
							name: 'Hawaii'
						}
					

Interfaces


						interface Pizza {
							slices: 4 | 8
							round: boolean
							name: 'Margherita' | 'Parmigiana'
						}

						const pizza: Pizza = {
							slices: -1, // ❌
							round: true,
							name: 'Margherita'
						}
					

Interfaces


						interface A {
							one: string
						}
						
						interface B extends A {
							two: number
							three?: string
						}
					

Interfaces


						interface Project {
							name: string,
							paymentBasis: 'fix' | 'hour'
						}
					

						interface GoodProject extends Project {
							paymentBasis: 'hour'
						}
					

Functions


						function add(x: number, y: number): number {
							return x + y
						}
						
						const add = (x: number, y: number): number => {
							return x + y
						}
					

						function choose<T, P>(a: T, b: P): T | P {
							if (something)
								return a
							else
								return b
						}
					

						const waitForMe = async (text:string): Promise<string> => text
					

Overloading


						function add(x: number): number
						function add(x: number, y: number = 1): number {
							return x + y
						}
					

						function add(a: string, b: string): string
						function add(a: number, b: number): number
						function add(a: string | number, b: string | number): string | number {
							if (a.constructor.name === 'String') return a + b
							else return a + b
						}
					

Classes


						class User {
							private id: string
							public readonly username: string
							friends: User[] = []

							constructor() {
								this.id = 'abc'
								this.username = 'John Doe'
							}

							private doSomeStuff() {}
						}
					

Generics


						function choose<T, P>(a: T, b: P): T | P {
							if (something)
								return a
							else
								return b
						}
					

						type Something<T> = {
							a: string,
							b: T
						}
					

Typescript Utilities Types

  • Partial & Required
  • Readonly
  • Pick & Omit

Partial / Required


						interface Props {
							a: number;
							b: string;
						};
						
						const x: Props = { a: 5 }; // Error: property 'b' missing
						
						const y: Partial<Props> = { a: 5 }; // OK
					

						interface Props {
							a?: number;
							b?: string;
						};
						
						const x: Props = { a: 5 }; // OK
						
						const y: Required<Props> = { a: 5 }; // Error: property 'b' missing
					

Readonly


						interface Todo {
							title: string;
						}
						
						const todo: Readonly<Todo> = {
							title: 'Delete inactive users',
						};
						
						todo.title = 'Hello'; // Error: cannot reassign a readonly property
					

Pick / Omit


						interface Todo {
							title: string;
							description: string;
							completed: boolean;
						}
						
						const todo: Pick<Todo, 'title' | 'completed'> = {
							title: 'Clean room',
							completed: false,
						};
					

						interface Todo {
							title: string;
							description: string;
							completed: boolean;
						}
						
						const todo: Omit<Todo, 'description'> = {
							title: 'Clean room',
							completed: false,
						};
					

Also there are...

  • Exclude & Extract
  • Record
  • NonNullable
  • ReturnType
  • InstanceType
  • ThisType

Examples

Constructor


						class Auto {
							wheels: number
						
							constructor(wheel: number) {
								this.wheels = wheel
							}
						}
					

						class Auto {
							constructor(private wheel: number) { }
						}
					

						class Auto {
							wheels!: number
						
							constructor(init: typeof Auto) {
								Object.assign(this, init)
							}
						}
					

Advanced Stuff


						class Auto {
							wheels?: number
							doors?: number
							// ...
						
							constructor(init: Partial<Auto>) {
								Object.assign(this, init)
							}
						}

						const a = new Auto({
							doors: 5,
						})
					

Advanced Stuff


						type RequireSome<T, K extends keyof T> = {
							[X in Exclude<keyof T, K>]?: T[X]
						} & {
							[P in K]-?: T[P]
						}

						class Auto {
							wheels!: number
							doors?: number
							// ...
						
							constructor(init: RequireSome<Auto, 'wheels'>) {
								Object.assign(this, init)
							}
						}

						const a = new Auto({
							wheels: 4,
							doors: 5,
						})
					

React Higher Order Components


						function withLayout<P extends object>(WrappedComponent: React.ComponentType<P>) {
							return (props: P) => (
								<div id='app'>
									<Header/>
									<WrappedComponent {...props}/>
									<Footer/>
								</div>
							);
						}