# Syntax
  ⚡️ Tags:
  
    📍Typescript
  
 # Types
# Enum
const enum Suit {
  Clubs,
  Diamonds,
  Hearts,
  Spades
}
var d = Suit.Diamonds;
enum Colors {
  Red = "RED",
  Green = "GREEN",
  Blue = "BLUE"
}
# Union type
type WindowStates = "open" | "closed" | "minimized";
type LockStates = "locked" | "unlocked";
type OddNumbersUnderTen = 1 | 3 | 5 | 7 | 9;
function rollDice(): 1 | 2 | 3 | 4 | 5 | 6 {
  return (Math.floor(Math.random() * 6) + 1) as 1 | 2 | 3 | 4 | 5 | 6;
}
const result = rollDice();
# Intersection type
type LinkedList<T> = T & { next: LinkedList<T> };
interface Person {
  name: string;
}
var people: LinkedList<Person>;
var s = people.name;
var s = people.next.name;
var s = people.next.next.name;
var s = people.next.next.next.name;
interface A {
  a: string;
  c: string;
}
interface B {
  b: string;
  c: number
}
type AB = A & B // { a: string; b: string: c: number };
type BA = B & A // { a: string; b: string: c: string };
# Tuple type
var x: [string, number];
x = ["hello", 10];
# never type
 The never type has the following characteristics:
- neveris a subtype of and assignable to every type.
- No type is a subtype of or assignable to never(exceptneveritself).
- In a function expression or arrow function with no return type annotation, if the function has no returnstatements, or onlyreturnstatements with expressions of type never, and if the end point of the function is not reachable (as determined by control flow analysis), the inferred return type for the function is never.
- In a function with an explicit neverreturn type annotation, allreturnstatements (if any) must have expressions of typeneverand the end point of the function must not be reachable.
Use case: Declare a function that throws an Error in TypeScript (opens new window)
function sometimesThrow(): number | never {
  if (Math.random() > 0.5) {
    return 100;
  }
  throw new Error('Something went wrong');
}
// 👇️ const result: number
const result = sometimesThrow();
console.log(result.toFixed());
WARNING
You can't specify the type of error a function throws
# void
we can only assign undefined or null to them.
let unusable: void = undefined;
let tempNum: void = undefined;  
function helloUser(): void {  
  alert("This is a welcome message");  
}  
# Generics
type StringArray = Array<string>;
type NumberArray = Array<number>;
type ObjectWithNameArray = Array<{ name: string }>;
# namespace vs. module
- “Internal modules” are closer to what most people would call a namespace
- “External modules” in JS speak really just are modulesnow.
// BEFORE
module Math {
    export function add(x, y) { ... }
}
// AFTER 
namespace Math {
    export function add(x, y) { ... }
}
# Assertion
# Assert Function
function multiply(x, y) {
  assert(typeof x === "number");
  assert(typeof y === "number");
  return x * y;
}
# const assertions
let foo = {
  name: "foo",
  contents: arr
} as const;
foo.name = "bar"; // error!
foo.contents = []; // error!
foo.contents.push(5); // ...works!
# Type parameters as constraints
function assign<T extends U, U>(target: T, source: U): T {
  for (let id in source) {
    target[id] = source[id];
  }
  return target;
}
let x = { a: 1, b: 2, c: 3, d: 4 };
assign(x, { b: 10, d: 20 });
assign(x, { e: 0 }); // Error
# Type guards
interface UserAccount {
  id: number;
  email?: string;
}
// access
user!.email!.length;
# Others
# Optional Chaining
let x = foo?.bar.baz();
// explain: 
// let x = foo === null || foo === undefined ? undefined : foo.bar.baz();
if (foo && foo.bar && foo.bar.baz) {
  // ...
}
// After-ish
if (foo?.bar?.baz) {
  // ...
}
# Dynamic import
async function getZipFile(name: string, files: File[]): Promise<File> {
  const zipUtil = await import("./utils/create-zip-file");
  const zipContents = await zipUtil.getContentAsBlob(files);
  return new File(zipContents, name);
}
# Computed properties
Recursive as well
type NeighborMap = { [name: string]: Node };
type Node = { name: string; neighbors: NeighborMap };
function makeNode(name: string, initialNeighbor: Node): Node {
  return {
    name: name,
    neighbors: {
      [initialNeighbor.name]: initialNeighbor,
    },
  };
}
# Class
# Readonly properties
interface Point {
  readonly x: number;
  readonly y: number;
}
class Foo {
  readonly a = 1;
  readonly b: string;
  constructor() {
    this.b = "hello"; // Assignment permitted in constructor
  }
}
# Decorators
function classDecorator<T extends { new (...args: any[]): {} }>(
  constructor: T
) {
  return class extends constructor {
    newProperty = "new property";
    hello = "override";
  };
}
@classDecorator
class Greeter {
  property = "property";
  hello: string;
  constructor(m: string) {
    this.hello = m;
  }
}
class C {
  @readonly
  @enumerable(false)
  method() { ... }
}
function readonly(target, key, descriptor) {
    descriptor.writable = false;
}
function enumerable(value) {
    return function (target, key, descriptor) {
        descriptor.enumerable = value;
    };
}
# with Json
interface MyObj {
    myString: string;
    myNumber: number;
}
let obj: MyObj = JSON.parse('{ "myString": "string", "myNumber": 4 }');
← NodeJs tools Types →