# JS and TS

# TS stuff

# Types and interfaces

type User = {
    name: string
}

interface User {
    name: string
}
  • Interfaces are made to represent objects and DTOs.
  • Types are made to make few types work as close as primative types, but it can go as complex as you need.
  • Interfaces can only be used to define type of object, type can be used for single type e.g. type SType = string | number
  • Types can use union of multiple types
type SType = { name: string } | { age: number}
type SType = { name: string } & { age: number}
const user: Stype = { name: 'string' }

# Use unknown instead of any

  • unknown is the union of every type there is.
  • any is the "elastic" type which fits to what it needs to be. (It may also be thought of as the switch to selectively disable type checking)
interface IUser {
    name: string
}

interface IAdminUser extends IUser {
    token: string;
    addNewUser: () => void;
}

// typeguard
function isAdminUser(object: unknown): object is IAdminUser {
    if (object !== null && typeof object === "object") {
        return "token" in object;
    }
    return false;
}

async function fetchUser() {
    const res = await fetch("someurl");

    const user: unknown = await res.json();
    if (isAdminUser()) {
        // then we know the type here
    }
}

# is Operator

type Species = 'cat' | 'dog';
interface Pet {
    species: Species;
}

class Cat implements Pet {
    public species: Species = 'cat';
    public meow(): void {
        console.log('meow');
    }
}
function petIsCat(pet: Pet): pet is Cat {
    return pet.species === 'cat';
}
const p: Pet = new Cat();

if (petIsCat(p)) {
    p.meow(); // can access
}

// type cast
(p as Cat).meow();

# satisfies

To match some type for inference purposes.

type UserImage = string | ICustomImage;

const user = {
    id: 1,
    image: "image-url"
} satisfies IUser;

# Enums

type State = "InProgress" | "Success" | "Fail"
or
enum State {
    InProgress = "InProgress"
    Success = "Success"
    Fail = "Fail"
} // do not use numbers
cosnt checkState = (state: State) => {};

# Utility

// to avoid having to create another interface to make fields optional when you only want to update a few fields
function updateProduct() {
    productId: IProduct["id"],
    updatedProduct: Partial<Omit<IProduct, "id">>   
} {}

// record
type Properties = "red" | "green" | "blue";
type RGB = [red: number, green: number, blue" number];
const color: Record<Properties, RGB | string> = {
    red: [255, 0, 0],
    green: 'green',
    blue: 'blue'
};

# JS stuff

# Arrow functions

const myFnc = () = {
    ...
}

No more issues with the this keyword!

# Exports and Imports

# Default export

import person from './person.js'

# Named export

import { smth } from './utility.js'
import * as bundled from './utility.js'

# Classes

Classes are a feature which basically replace constructor functions and prototypes. You can define blueprints for JavaScript objects with them.

class Human {
    constructor() {
        this.gender = 'male';
    }
}
class Person extends Human {
    constructor() {
        super();
        this.name = 'test';
    }
}
const person = new Person();

# Spread/Rest operators

Spread is used to split up array elements or object properties

const arr = [...oldArr, 1, 2]
const newObj = {...oldObj, newProp: 5}

Rest is used to merge a list of function arguments into an array

function sortArgs(...args) {
    return args.sort()
}

# Destructing

Easily extract array elements or object properties and store them in variables

[a, b] = ['Hello', 'World']
{name} = {name: 'Name', age: 1}

# Reference and primitive types

Objects and arrays are reference types (just copy the pointer)

Use spread operator to copy.

const secondPerson = {
    ...person
}

# Arrow functions

An arrow function expression is a compact alternative to a traditional function expression, with some semantic differences and deliberate limitations in usage:

  • Arrow functions don't have their own bindings to this, arguments, or super, and should not be used as methods.
  • Arrow functions cannot be used as constructors. Calling them with new throws a TypeError. They also don't have access to the new.target keyword.
  • Arrow functions cannot use yield within their body and cannot be created as generator functions.
param => expression

(param) => expression

(param1, paramN) => expression

param => {
  statements
}

(param1, paramN) => {
  statements
}

# References