//// What is TypeScript?
// ts is super set of js
// + types
// + typecheck
// + transpiler(like babel)
// + many more
//// Setup TypeScript compiler
// npm i typescript -g # install typescript compiller
// tsc file.ts # compile files file.ts to file.js
// tsc init # crate package.json
// tsc -p . # run using package.json in cwd
// tsc -p . -w # watch mode
// use "strict": true
//// JavaScript
// two types of values
// primitives: string, number, boolean, undefined
// references: function, object
// note: class is function and class instance is object
// note: null is also object
// typescript adds: enum, type, interface
// and many more: is, in, keyof, any, never, void...
//// Variable Type Declaration
// variableName colon variableType
() => {
// declare by type
let trueFalse: boolean
let bar: number
let text: string
let myArray: string[] = ["foo"]
let tuple: [string, number, boolean] = ["bar", 1, false]
function bas(myNumber: number): void {
}
// declare by value
let active = false
let array = [0, 1, "string"]
// any
let anyValue: any = 123 // don't use it
// Type assertions
let myValue = 1 as any as string // don't use it
}
//// ES6+ is here
() => {
// array destructuring
let [first, second] = [1, 2]
let [one, ...rest] = [1, 2, 3, 4]
let [, two, , four] = [1, 2, 3, 4]
// object destructuring
let { a, b } = { a: 1, b: 2 }
let { c, ...passthrough } = { c: 1, d: 2 }
let { a: newName1, b: newName2 } = { a: 1, b: 2 }
let { e, f: newName3 = "a" } = { e: 1 };
// variable swap
[first, second] = [second, first]
// array spread
let firstArray = [1, 2]
let secondArray = [3, 4]
let bothPlus = [0, ...firstArray, ...secondArray, 5]
// object spread
let defaults = { a: 1 }
let entered = { a: 2 }
let search = { ...defaults, ...entered }
// overkill
function f({ a, b = 0 } = { a: "" }): { a: 1 } | void {
// ...
}
// more at
// http://es6-features.org
}
//// Declaration spaces
// Value X Type X Namespace
() => {
// class creates type and value
class MyClass {
}
let instance: MyClass = new MyClass()
// enum creates type and value
enum MyEnum {
value = 0
}
let value: MyEnum = MyEnum.value
// interface creates only type
// global scope
interface MyInterface {
}
// let myInterface: MyInterface = MyInterface // error
// type creates only type
type MyType = {
}
// let myType: MyType = MyType // error
// function creates only value
function myFunction() {
}
// let foo: myFunction = myFunction // error
// value creates only value
let myNumber = 123
// let foo: myNumber = myNumber // error
// convert value to type
let myNextVariable: typeof myNumber
// remember: only class, enum, interface, type creates types
}
//// Types
() => {
// String Literal Types
function bar(color: "green" | "red") {
// color = "white" // error
}
interface SomeInterface {
// Class Constructor Type
new(foo: number, bar: number): SomeInterface
// Function Type
replace(heystack: string, needle: string): string
// Index Type
[index: number]: string
// this Type
returnInstance(): this
}
}
//// Functions
() => {
// optional parameters
// spread operator
// optional return types
// this type
function foo(this: HTMLElement, arg?: number, ...rest: number[]): boolean {
this.innerHTML
return true
}
// anonymous
// default value
let anonymousFunc = (arg: number = 1): boolean => {
return true
}
}
//// Type alias
// creates type
() => {
type trueFalseOrNothing = boolean | "nothing"
let foo: trueFalseOrNothing = false
type Circle = {
radius: number,
}
let circle: Circle = { radius: 10 }
// cannot be "extends"
}
// local scope
// let foo: trueFalseOrNothing // error
//// Interface
// creates type
// polutes entire file scope (or use namespaces)
// can be "extends"
interface Base {
type: string
}
interface Human extends Base {
type: "human"
age: number
}
interface Animal extends Base {
type: "animal"
age: number
}
// later on I might need human's name
// declaration merging
// don't forget readonly and optional
interface Human extends Base {
readonly name?: string
}
() => {
function createHuman(): Human {
return { type: "human", age: 1 } // add name
}
function updateHuman(human: Human) {
human.age++
// human.type = "worker" // error
}
}
// global scope
let myAnimal: Animal
//// Enum
// similar to other languages
() => {
// indexed members
enum MyEnum {
foo = 1,
bar
}
// multiple values
enum FileAccess {
// constant members
None,
Read = 1 << 1,
Write = 1 << 2,
ReadWrite = Read | Write,
// computed member
G = "123".length
}
FileAccess.ReadWrite
// string value
enum MyEnumString {
foo = "bar"
}
}
// local scope
// MyEnumString.foo // error
//// Class
// can "extends" classes and "implements" types
// abstract classes
// you can define it's properties
// modifiers: public(anyone, default), private(current class), protected(current and childs)
// don't forget readonly and optional
// static variables and function
// constructor properties
() => {
class Foo {
}
abstract class AnimalAbstract extends Foo implements Animal {
type: "animal"
age: number
}
// let animalAbstract = new AnimalAbstract() // error
class Fish extends AnimalAbstract {
private readonly color?: string
static ocean = "Atlantic"
constructor(public name: string) {
super()
}
protected walk() {
}
}
// super
// get set
class GoldFish extends Fish {
walk() {
super.walk()
}
get description() {
return this.type + this.name
}
set birthDate(date: number) {
this.age = new Date().getTime() - date
}
}
}
// local scope
// let myGoldFish: GoldFish
//// Union type |
// defines that value can have multiple types
() => {
function bar(arg: string | number | HTMLElement) {
arg
}
// used in optional arguments
function foo(optionalArg?: string) {
optionalArg
}
}
//// Intersection Types &
// for extending properties
() => {
type Loggable = { log(): void }
type LoggableHuman = Human & Loggable
let human = {} as LoggableHuman
human
// used in
Object.assign
}
//// Type Guards
// ensures value type
() => {
// using typeof
function foo(optionalArg?: string | Function) {
if(typeof optionalArg == "undefined") {
optionalArg
return
}
else if(typeof optionalArg == "function") {
optionalArg
return optionalArg
}
else {
optionalArg
return optionalArg
}
}
// using instanceof
function bar(arg: Event | HTMLElement) {
if(arg instanceof HTMLElement) {
arg
}
else {
arg
}
}
// using user defined type guard
// check obj.type
function isAnimal(obj: Human | Animal): obj is Animal {
return obj.type == "animal"
}
// type never
function myFunction(name: string) {
if(typeof name == "string") {
name
}
else {
name
}
}
}
//// Namespaces
namespace Shapes {
export namespace Polygons {
export class Triangle { }
export class Square { }
}
}
new Shapes.Polygons.Triangle()
import polygons = Shapes.Polygons
let sq = new polygons.Square();
//// Generics
// you might need to pass types into functions and classes
() => {
function loadAnimalFromServer(): Promise<Animal> {
return new Promise((resolve) => { })
}
loadAnimalFromServer().then(animal => {
})
function createInstance<A extends Animal>(animalClass: new() => A): A {
return new animalClass()
}
}
//// Truthy
if("") { } // false
if(NaN) { } // false
if(undefined) { } // false
if(null) { } // false
if({}) { } // true
if([]) { } // true
if(undefined == null) { } // true
if(false == "") { } // true
if(false == 0) { } // true
if(0 == "") { } // true
if(0 == null) { } // ?
//// You don't need null
// use undefined instead
// https://github.com/Microsoft/TypeScript/wiki/Coding-guidelines#null-and-undefined
//// Modules
// same ES6 syntax
// import a from "b"
export let number = 1;
// you can import/export namespaces, types and values
// barrel: export * from "./elements/Spacer"
//// More tips
() => {
// Make all properties in T optional
let partial: Partial<Human> = { name: "Paul" }
// see declaration
// Make all properties in T readonly
let readonly: Readonly<Human> = { type: "human", name: "Paul", age: 3 }
// readonly.name = "me" // error
// see declaration
// Construct a type with a set of properties K of type T
let record: Record<"hmm", Performance>
// see declaration
// learn about javascript call stack
// https://www.youtube.com/watch?v=8aGhZQkoFbQ
}
Last active
March 13, 2020 18:27
-
-
Save pravdomil/fe7d0233f475556e98f1ca963344ea8c to your computer and use it in GitHub Desktop.
Learn all TypeScript features in 10 + 3min
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment