gruckion / learning

Learning stuff
0 stars 0 forks source link

Typescript #33

Open gruckion opened 5 years ago

gruckion commented 5 years ago

Intersection Types

This produces a type that has both Quckable and Flyable properties.

type Duck = Quckable & Flyable;

Union Types

type Flyable = Eagle | Butterfly;

This produces a type that has the overlap properties of Eagle and Butterfly.

Custom Type Guards

If you do not want to cast a type as string but have some custom logic to see if an object belongs to a type then you can do;

const canFly = (animal: Animal): animal is Flyable =>
    typeof (animal as any).fly === "function";

if (canFly(animal)) {
    animal.fly();
}

animal is Flyable is a boolean, this is a safer cast.

Type assertion

Used when you know the value is not null | undefined

person.children[0]!.name;

Literal Types

Since types are sets you can use literal types, that is a set of one value.

type Move "rock" | "Paper" "Scissor";

Never return functions

const throws =(): never => {
    throw new Error("This never returns");
}
const loops = (): never => {
    while (true) {
       console.log("This never returns either");
    }
}

Using unknown over any

If the user is inputting a value and you do not know what it is. You should use unknown.

let a: string;

let x: any;
a = x; // Compiles
x = a; // Compiles

let y: unknown;
y = a; // Compiles
a = y; // Does not compile

Using unknown allows you to avoid assigning a: string to the value of y: unknown since y is unknown. If you use x: any then this will not be caught.

Index Types

type Duck {
    colors: string;
    feathers: number;
}

type DuckProps = keyof Duck; // = "colors" | "feathers"
type ColorType = Duck["colors"]; // = string
type DuckValues = Duck[DuckProps] // = string | number

Here keyof gives the set of possible keys on the interface.

Conditional Types

This allows us to have assign different types based on the input T being a boolean or not.

type StringOrNumber<T> = T extends boolean ? string : number;

type T1 = StringOrNumber<true>; // string
type T2 = StringOrNumber<false>; // string
type T3 = StringOrNumber<Object>; // number

Example

type TypeName<T> =
    T extends string ? "string" :
    T extends number ? "number" :
    T extends boolean ? "boolean" :
    T extends undefined ? "undefined" :
    T extends Function ? "function" :
    "object";

type T0 = TypeName<string>; // "string"

A simpler version of the above would be.

type TypeName<T> = nameof(T);

If restricting to just the above types

type TypeName<T> =
    ["string", "number", "boolean", "undefined", "Function"]
    .includes(nameof(T));
``

## Infer

 `infer` Is a specific key word that you can use within a conditional type and is used on the right side of `extends`.

```ts
type ElementType<T> = T extends (infer U)[] ? U : never;
type T = ElementType<[]>; // = never
type T1 = ElementType<string[]>; // = string

If T is an array of U then resolve to the type U.

Functional Programming

The principle of separating the data structures from the objects. An object is a class that has functions and methods while the data structure is an object that represents pure data.

One step further is we don't need objects, most of the time. We just need functions that do work on those data structures.


interface PersonDto {
    id: number;
    givenName: string;
    familyName: string;
}

interface Person {
    id: string;
    fullName: string;
}

const transformPerson = (dto: PersonDto): Person => {
    return {
        id: `${dto.id}`,
        fullName: `${dto.givenName} ${dto.familyName}`
    }
}
``
gruckion commented 5 years ago

Discriminate Unions

https://www.youtube.com/watch?v=TtDP6lpSjWc