Skip to content

Instantly share code, notes, and snippets.

@zeyadetman
Last active January 1, 2024 01:30
Show Gist options
  • Save zeyadetman/dd2330b49f2c86a9425da443bd7ed316 to your computer and use it in GitHub Desktop.
Save zeyadetman/dd2330b49f2c86a9425da443bd7ed316 to your computer and use it in GitHub Desktop.

Welcome

TypeScript, Understanding the code you write

    :-====-:
   -+-. .:-+**-
  +=   =+:...-*+
 :*   ==  :=   *:
 :*   == -+.   *:
 :*   .**-   :+-
 :*  -+-   :+-
 :*-+-   :+++.
 :*-   :+=  :+=.
 :*   -+:+=   :*.
 :*   +-  ==   *:
  *:  :*:    .=*.
  .+=. .-===+*+.
    :===--===:


Agenda

  • How it works
  • Narrowing
  • keyof operator
  • in operator
  • Generics
  • Mapped Types
  • as const
  • typescript coverage
  • Practice

How it works

Browsers Cannot understand TypeScript




~~~graph-easy --as=boxart
[ TYPESCRIPT ] - Compilation/Transpiling -> [ JAVASCRIPT ]
~~~
~~~graph-easy --as=boxart
[ const a: number = 5; ] - Compilation/Transpiling -> [ const a = 5; ]
~~~

How it works

TS                VS.         C#
Compile Time      VS.         Runtime

Function Overload in C#

void display() { ... }
void display(int a) { ... }
float display(double a) { ... }
float display(int a, float b) { ... }

How it works

Typescript is gone before Runtime

Function Overload in Typescript

// typescript
function makeDate(timestamp: number): Date;
function makeDate(m: number, d: number, y: number): Date;
function makeDate(mOrTimestamp: number, d?: number, y?: number): Date {
  if (d !== undefined && y !== undefined) {
    return new Date(y, mOrTimestamp, d);
  } else {
    return new Date(mOrTimestamp);
  }
}

TO

// javascript
function makeDate(mOrTimestamp, d, y) {
  if (d !== undefined && y !== undefined) {
      return new Date(y, mOrTimestamp, d);
  }
  else {
      return new Date(mOrTimestamp);
  }
}

How it works

Typescript is gone before Runtime

Function Overload in Typescript


// typescript
function makeDate(timestamp: number): Date;
function makeDate(m: number, d: number, y: number): Date;
function makeDate(mOrTimestamp: number, d?: number, y?: number): Date {
  if (d !== undefined && y !== undefined) {
    return new Date(y, mOrTimestamp, d);
  } else {
    return new Date(mOrTimestamp);
  }
}

TO

// javascript
function makeDate(mOrTimestamp, d, y) {
  if (d !== undefined && y !== undefined) {
      return new Date(y, mOrTimestamp, d);
  }
  else {
      return new Date(mOrTimestamp);
  }
}

How it works

Typescript is gone before Runtime

Function Overload


// typescript
function makeDate(timestamp: number): Date;
function makeDate(m: number, d: number, y: number): Date;
function makeDate(mOrTimestamp: number, d?: number, y?: number): Date {
  if (d !== undefined && y !== undefined) {
    return new Date(y, mOrTimestamp, d);
  } else {
    return new Date(mOrTimestamp);
  }
}

TO

// javascript
function makeDate(mOrTimestamp, d, y) {
  if (d !== undefined && y !== undefined) {
      return new Date(y, mOrTimestamp, d);
  }
  else {
      return new Date(mOrTimestamp);
  }
}

How it works

Zod Runtime Typechecking for TypeScript

Narrowing (make it less wide)

TS determines the variable type from the code context

function example(x: string | number, y: string | boolean) {
  if (x === y) {
    x.toUpperCase();
    y.toLowerCase();
  } else {
    console.log(x);
    console.log(y);
  }
}

Narrowing (make it less wide)

TS determines the variable type from the code context

function example(x: string | number, y: string | boolean) {
  if (x === y) {
    // We can now call any 'string' method on 'x' or 'y'.
    x.toUpperCase();
          // (method) String.toUpperCase(): string

    y.toLowerCase();
          // (method) String.toLowerCase(): string

  } else {
    console.log(x);
          // (parameter) x: string | number

    console.log(y);
          // (parameter) y: string | boolean
  }
}

Narrowing (make it less wide)

The inoperator narrowing

type Fish = { swim: () => void };
type Bird = { fly: () => void };
type Human = { swim?: () => void; fly?: () => void };

function move(animal: Fish | Bird | Human) {
  if ("swim" in animal) {
    animal;
  } else {
    animal;
  }
}

Narrowing (make it less wide)

The inoperator narrowing

type Fish = { swim: () => void };
type Bird = { fly: () => void };
type Human = { swim?: () => void; fly?: () => void };

function move(animal: Fish | Bird | Human) {
  if ("swim" in animal) {
    animal;
      // (parameter) animal: Fish | Human

  } else {
    animal;
      // (parameter) animal: Bird | Human

  }
}

Narrowing (make it less wide)

instanceofnarrowing

function logValue(x: Date | string) {
  if (x instanceof Date) {
    console.log(x.toUTCString());
  } else {
    console.log(x.toUpperCase());
  }
}

Narrowing (make it less wide)

instanceofnarrowing

function logValue(x: Date | string) {
  if (x instanceof Date) {
    console.log(x.toUTCString());
        // (parameter) x: Date
  } else {
    console.log(x.toUpperCase());
        // (parameter) x: string
  }
}

Narrowing (make it less wide)

instanceofnarrowing

function logValue(x: Date | string) {
  if (x instanceof Date) {
    console.log(x.toUTCString());
        // (parameter) x: Date
  } else {
    console.log(x.toUpperCase());
        // (parameter) x: string
  }
}

keyof

Extract keys or properties of a typein a union format

if no object then never will be returned

const scheduler = {
  id: 2,
  name: "Test",
  internalCategoryId: 4,
}

We need to extract the scheduler keys

// Result

type schedulerKeys = "id" | "name" | "internalCategoryId";

keyof

const scheduler = {
  id: 2,
  name: "Test",
  internalCategoryId: 4,
}
type schedulerType = typeof scheduler
type schedulerKeys = keyof schedulerType

playground


keyof

const scheduler = {
  id: 2,
  name: "Test",
  internalCategoryId: 4,
}
type schedulerType = typeof scheduler
type schedulerKeys = keyof schedulerType

playground


in operator

type namesIdsLists = {
  picker: FilterOption[];
  deliveryPerson: FilterOption[];
  internalCategory: FilterOption[];
  fp: FilterOption[];
}

in operator

type namesIdsLists = {
  picker: FilterOption[];
  deliveryPerson: FilterOption[];
  internalCategory: FilterOption[];
  fp: FilterOption[];
}
type listTypes = "picker" | "deliveryPerson" | "internalCategory" | "fp";
type namesIdsLists = {[k in listTypes]: FilterOption[]}

Generics

Think of it like function in TS

interface BasicType {
  input: string;
}

const x: BasicType = { input: "test" };

Generics

Think of it like function in TS

interface BasicType<T> {
  input: T;
}

const x: BasicType<string> = { input: "test" };
const y: BasicType<number> = { input: "test" }; // wrong

Generics

Think of it like function in TS

function basic(a, b) {
  return { a, b };
}

Generics

Think of it like function in TS

function basic<A, B>(a, b) {
  return { a, b };
}

Generics

Think of it like function in TS

function basic<A, B>(a: A, b: B) {
  return { a, b };
}

Generics

Think of it like function in TS

function basic<A, B>(a: A, b: B): {a: A, b: B} {
  return { a, b };
}

basic<string, number>("hello", 2);

Generics

[If] Condition

function isNumber(item) {
  if(typeof item === 'number') return true;

  return false
}

Generics

[If] Condition

type IsNumber<T> = T extends number ? true : false;

function isNumber<T>(item: T): IsNumber<T> {
  if(typeof item === 'number') return true;
      // Type 'boolean' is not assignable to type 'IsNumber<T>'.(2322)

  return false;
      // Type 'boolean' is not assignable to type 'IsNumber<T>'.(2322)
}

Generics

[If] Condition

type IsNumber<T> = T extends number ? true : false;

function isNumber<T>(item: T): IsNumber<T> {
  if(typeof item === 'number') return true as IsNumber<T>;
      // Type 'boolean' is not assignable to type 'IsNumber<T>'.(2322)

  return false as IsNumber<T>;
      // Type 'boolean' is not assignable to type 'IsNumber<T>'.(2322)
}

Generics

[If] Condition

type IsNumber<T> = T extends number ? true : false;

function isNumber<T>(item: T): IsNumber<T>
function isNumber(item: number): true
function isNumber<T>(item: number) {
  if(typeof item === 'number') return true;

  return false;
}

Playground


Mapped Types

mapped types

[Key in Type]

Playground


as const

Object.freeze in compile time Note: Object.freeze only top level, but const assertion entire object

const x = [1,2];
 // typeof x -> number[]
const x = [1,2] as const;
 // typeof x -> readonly [1,2]

typescript coverage

Generate Coverage Report


Resources

Notes on TypeScript

Time to practice

Resources


Closing





                      ___                     _    _                    ___
                     / _ \  _   _   ___  ___ | |_ (_)  ___   _ __   ___|__ \
                    | | | || | | | / _ \/ __|| __|| | / _ \ | '_ \ / __| / /
                    | |_| || |_| ||  __/\__ \| |_ | || (_) || | | |\__ \|_|
                     \__\_\ \__,_| \___||___/ \__||_| \___/ |_| |_||___/(_)

Closing





                         _____  _                    _
                        |_   _|| |__    __ _  _ __  | | __ ___
                          | |  | '_ \  / _` || '_ \ | |/ // __|
                          | |  | | | || (_| || | | ||   < \__ \
                          |_|  |_| |_| \__,_||_| |_||_|\_\|___/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment