Skip to content

Instantly share code, notes, and snippets.

@evilz
Last active July 17, 2023 10:21

Revisions

  1. evilz renamed this gist Jul 17, 2023. 1 changed file with 69 additions and 71 deletions.
    140 changes: 69 additions & 71 deletions gistfile1.txt → Typescript.md
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    1.Optional Chaining (?.):
    # 1.Optional Chaining (?.):
    Optional chaining allows you to safely access nested properties or methods without worrying about null or undefined values. It short-circuits the evaluation if any intermediate property is null or undefined.

    ```ts
    @@ -17,22 +17,32 @@ const invalidCode = user.address?.postalCode?.toLowerCase();
    console.log(invalidCode); // Output: undefined
    ```

    2.Nullish Coalescing Operator (??):
    # 2.Nullish Coalescing Operator (??):
    The nullish coalescing operator provides a default value when a variable is null or undefined.
    ```ts
    const name = null;
    const defaultName = name ?? 'Unknown';
    console.log(defaultName); // Output: Unknown

    const age = 0;
    const defaultAge = age ?? 18;
    console.log(defaultAge); // Output: 0
    3.Type Assertion:
    ```

    # 3.Type Assertion:
    Type assertion allows you to explicitly define the type of a variable when TypeScript is unable to infer it.
    const userInput: unknown = 'Hello World';

    ```ts
    let userInput: unknown;
    userInput = "Hello World";
    const strLength = (userInput as string).length;
    console.log(strLength); // Output: 11
    4.Generics:
    ```

    # 4.Generics:
    Generics enable you to create reusable components that can work with a variety of types.

    ```ts
    function reverse<T>(items: T[]): T[] {
    return items.reverse();
    }
    @@ -44,8 +54,12 @@ console.log(reversedNumbers); // Output: [5, 4, 3, 2, 1]
    const strings = ['a', 'b', 'c'];
    const reversedStrings = reverse(strings);
    console.log(reversedStrings); // Output: ['c', 'b', 'a']
    5.keyof Operator:
    ```

    # 5.keyof Operator:
    The keyof operator returns a union of all known property names of a given type.

    ```ts
    interface User {
    id: number;
    name: string;
    @@ -66,8 +80,12 @@ const name = getUserProperty(user, 'name');
    console.log(name); // Output: John Doe

    const invalidProperty = getUserProperty(user, 'age'); // Error: Argument of type '"age"' is not assignable to parameter of type '"id" | "name" | "email"'
    6.Type Guards:
    ```

    # 6.Type Guards:
    Type guards allow you to narrow down the type of a variable within a conditional block, based on a certain condition.

    ```ts
    function logMessage(message: string | number) {
    if (typeof message === 'string') {
    console.log('Message: ' + message.toUpperCase());
    @@ -78,8 +96,12 @@ function logMessage(message: string | number) {

    logMessage('hello'); // Output: Message: HELLO
    logMessage(3.14159); // Output: Value: 3.14
    7.Intersection Types:
    ```

    # 7.Intersection Types:
    Intersection types allow you to combine multiple types into a single type, creating a new type that has all the properties and methods of the intersected types.

    ```ts
    interface Loggable {
    log: () => void;
    }
    @@ -128,8 +150,12 @@ const partialUser: PartialUser = {
    };

    console.log(partialUser); // Output: { name: 'John Doe', email: 'john@example.com' }
    9.String Literal Types and Union Types:
    ```

    # 9.String Literal Types and Union Types:
    TypeScript supports string literal types and union types, which can be used to define specific sets of values for a variable.

    ```ts
    type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';

    function sendRequest(url: string, method: HttpMethod) {
    @@ -140,8 +166,12 @@ sendRequest('/users', 'GET');
    sendRequest('/users', 'POST');
    sendRequest('/users/1', 'PUT');
    sendRequest('/users/1', 'DELETE');
    10.Decorators:
    ```

    # 10.Decorators:
    Decorators allow you to modify or extend the behavior of classes, methods, properties, and other declarations.

    ```ts
    function uppercase(target: any, propertyKey: string) {
    let value = target[propertyKey];

    @@ -166,8 +196,12 @@ class Person {
    const person = new Person();
    person.name = 'John Doe';
    console.log(person.name); // Output: JOHN DOE
    11.Index Signatures:
    ```

    # 11.Index Signatures:
    Index signatures allow you to define dynamic property names and their corresponding types in an interface or type.

    ```ts
    interface Dictionary {
    [key: string]: number;
    }
    @@ -180,8 +214,12 @@ const scores: Dictionary = {

    console.log(scores['math']); // Output: 90
    console.log(scores['english']); // Output: undefined
    12.Type Inference with Conditional Statements:
    ```

    # 12.Type Inference with Conditional Statements:
    TypeScript can infer the types based on conditional statements, allowing for more concise code.

    ```ts
    function calculateTax(amount: number, isTaxable: boolean) {
    if (isTaxable) {
    return amount * 1.1; // Type: number
    @@ -195,8 +233,12 @@ console.log(taxableAmount.toFixed(2)); // Output: 110.00

    const nonTaxableAmount = calculateTax(100, false);
    console.log(nonTaxableAmount.toFixed(2)); // Output: 100.00
    13.Readonly Properties:
    ```

    # 13.Readonly Properties:
    TypeScript provides the readonly modifier to define properties that can't be modified after initialization.

    ```ts
    class Circle {
    readonly radius: number;

    @@ -215,8 +257,12 @@ console.log(circle.radius); // Output: 5
    // circle.radius = 10; // Error: Cannot assign to 'radius' because it is a read-only property

    console.log(circle.getArea()); // Output: 78.53981633974483
    14.Type Aliases:
    ```

    # 14.Type Aliases:
    Type aliases allow you to create custom names for existing types, providing more semantic meaning and improving code readability.

    ```ts
    type Point = {
    x: number;
    y: number;
    @@ -230,8 +276,12 @@ function draw(shape: Shape, position: Point) {

    const startPoint: Point = { x: 10, y: 20 };
    draw('circle', startPoint); // Output: Drawing a circle at (10, 20)
    15.Type Guards with Classes:
    ```

    # 15.Type Guards with Classes:
    Type guards can also be used with classes to narrow down the type of an object instance.

    ```ts
    class Animal {
    name: string;
    constructor(name: string) {
    @@ -258,55 +308,11 @@ const animal = new Animal('Unknown');

    makeSound(dog); // Output: Woof!
    makeSound(animal); // Output: Unknown animal
    Top comments (6)

    Subscribe
    pic
    Add to the discussion


    vickodev profile image
    Vıɔk A Hıƃnıʇɐ C.
    16 juil.

    Hey bro, great post!!
    A small observation. For point 8 you can use the Partial Type like this:
    interface User {
    id: number;
    name: string;
    email: string;
    }

    type PartialUser = Partial<User>;

    const partialUser: PartialUser = {
    name: "Nikola Tesla",
    email: "nikola@teslaxcorp.com"
    };
    Even, add new properties, for example:
    type MyOwnUser = Partial<User> & { age: number };

    const ownUser: MyOwnUser = {
    name: "Nikola Tesla",
    email: "nikola@teslaxcorp.com",
    age: 27
    };

    15
    likes
    Like
    Reply


    samuel-braun profile image
    Samuel Braun
    16 juil. • Edited on 16 juil.
    ```

    Another one I enjoy quiet often is the const assertion. With them you can make stuff readonly outside of class members. For example:
    # 16 Const assertion

    With as const:
    ```ts
    // Type '"hello"'
    let x = "hello" as const;

    @@ -315,12 +321,4 @@ let y = [10, 20] as const;

    // Type '{ readonly text: "hello" }'
    let z = { text: "hello" } as const;
    Without as const:
    // Type 'string'
    let x = "hello";

    // Type 'number[]'
    let y = [10, 20];

    // Type '{ text: string }'
    let z = { text: "hello" };
    ```
  2. evilz created this gist Jul 17, 2023.
    326 changes: 326 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,326 @@
    1.Optional Chaining (?.):
    Optional chaining allows you to safely access nested properties or methods without worrying about null or undefined values. It short-circuits the evaluation if any intermediate property is null or undefined.

    ```ts
    const user = {
    name: 'John',
    address: {
    city: 'New York',
    postalCode: '12345'
    }
    };

    const postalCode = user.address?.postalCode;
    console.log(postalCode); // Output: 12345

    const invalidCode = user.address?.postalCode?.toLowerCase();
    console.log(invalidCode); // Output: undefined
    ```

    2.Nullish Coalescing Operator (??):
    The nullish coalescing operator provides a default value when a variable is null or undefined.
    const name = null;
    const defaultName = name ?? 'Unknown';
    console.log(defaultName); // Output: Unknown

    const age = 0;
    const defaultAge = age ?? 18;
    console.log(defaultAge); // Output: 0
    3.Type Assertion:
    Type assertion allows you to explicitly define the type of a variable when TypeScript is unable to infer it.
    const userInput: unknown = 'Hello World';
    const strLength = (userInput as string).length;
    console.log(strLength); // Output: 11
    4.Generics:
    Generics enable you to create reusable components that can work with a variety of types.
    function reverse<T>(items: T[]): T[] {
    return items.reverse();
    }

    const numbers = [1, 2, 3, 4, 5];
    const reversedNumbers = reverse(numbers);
    console.log(reversedNumbers); // Output: [5, 4, 3, 2, 1]

    const strings = ['a', 'b', 'c'];
    const reversedStrings = reverse(strings);
    console.log(reversedStrings); // Output: ['c', 'b', 'a']
    5.keyof Operator:
    The keyof operator returns a union of all known property names of a given type.
    interface User {
    id: number;
    name: string;
    email: string;
    }

    function getUserProperty(user: User, property: keyof User) {
    return user[property];
    }

    const user: User = {
    id: 1,
    name: 'John Doe',
    email: 'john@example.com'
    };

    const name = getUserProperty(user, 'name');
    console.log(name); // Output: John Doe

    const invalidProperty = getUserProperty(user, 'age'); // Error: Argument of type '"age"' is not assignable to parameter of type '"id" | "name" | "email"'
    6.Type Guards:
    Type guards allow you to narrow down the type of a variable within a conditional block, based on a certain condition.
    function logMessage(message: string | number) {
    if (typeof message === 'string') {
    console.log('Message: ' + message.toUpperCase());
    } else {
    console.log('Value: ' + message.toFixed(2));
    }
    }

    logMessage('hello'); // Output: Message: HELLO
    logMessage(3.14159); // Output: Value: 3.14
    7.Intersection Types:
    Intersection types allow you to combine multiple types into a single type, creating a new type that has all the properties and methods of the intersected types.
    interface Loggable {
    log: () => void;
    }

    interface Serializable {
    serialize: () => string;
    }

    type Logger = Loggable & Serializable;

    class ConsoleLogger implements Loggable {
    log() {
    console.log('Logging to console...');
    }
    }

    class FileLogger implements Loggable, Serializable {
    log() {
    console.log('Logging to file...');
    }

    serialize() {
    return 'Serialized log data';
    }
    }

    const logger1: Logger = new ConsoleLogger();
    logger1.log(); // Output: Logging to console...

    const logger2: Logger = new FileLogger();
    logger2.log(); // Output: Logging to file...
    console.log(logger2.serialize()); // Output: Serialized log data
    8.Mapped Types:
    Mapped types allow you to create new types by transforming the properties of an existing type.
    interface User {
    id: number;
    name: string;
    email: string;
    }

    type PartialUser = { [K in keyof User]?: User[K] };

    const partialUser: PartialUser = {
    name: 'John Doe',
    email: 'john@example.com'
    };

    console.log(partialUser); // Output: { name: 'John Doe', email: 'john@example.com' }
    9.String Literal Types and Union Types:
    TypeScript supports string literal types and union types, which can be used to define specific sets of values for a variable.
    type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';

    function sendRequest(url: string, method: HttpMethod) {
    // send request logic here...
    }

    sendRequest('/users', 'GET');
    sendRequest('/users', 'POST');
    sendRequest('/users/1', 'PUT');
    sendRequest('/users/1', 'DELETE');
    10.Decorators:
    Decorators allow you to modify or extend the behavior of classes, methods, properties, and other declarations.
    function uppercase(target: any, propertyKey: string) {
    let value = target[propertyKey];

    const getter = () => value;
    const setter = (newValue: string) => {
    value = newValue.toUpperCase();
    };

    Object.defineProperty(target, propertyKey, {
    get: getter,
    set: setter,
    enumerable: true,
    configurable: true
    });
    }

    class Person {
    @uppercase
    name: string;
    }

    const person = new Person();
    person.name = 'John Doe';
    console.log(person.name); // Output: JOHN DOE
    11.Index Signatures:
    Index signatures allow you to define dynamic property names and their corresponding types in an interface or type.
    interface Dictionary {
    [key: string]: number;
    }

    const scores: Dictionary = {
    math: 90,
    science: 85,
    history: 95
    };

    console.log(scores['math']); // Output: 90
    console.log(scores['english']); // Output: undefined
    12.Type Inference with Conditional Statements:
    TypeScript can infer the types based on conditional statements, allowing for more concise code.
    function calculateTax(amount: number, isTaxable: boolean) {
    if (isTaxable) {
    return amount * 1.1; // Type: number
    } else {
    return amount; // Type: number
    }
    }

    const taxableAmount = calculateTax(100, true);
    console.log(taxableAmount.toFixed(2)); // Output: 110.00

    const nonTaxableAmount = calculateTax(100, false);
    console.log(nonTaxableAmount.toFixed(2)); // Output: 100.00
    13.Readonly Properties:
    TypeScript provides the readonly modifier to define properties that can't be modified after initialization.
    class Circle {
    readonly radius: number;

    constructor(radius: number) {
    this.radius = radius;
    }

    getArea() {
    return Math.PI * this.radius ** 2;
    }
    }

    const circle = new Circle(5);
    console.log(circle.radius); // Output: 5

    // circle.radius = 10; // Error: Cannot assign to 'radius' because it is a read-only property

    console.log(circle.getArea()); // Output: 78.53981633974483
    14.Type Aliases:
    Type aliases allow you to create custom names for existing types, providing more semantic meaning and improving code readability.
    type Point = {
    x: number;
    y: number;
    };

    type Shape = 'circle' | 'square' | 'triangle';

    function draw(shape: Shape, position: Point) {
    console.log(`Drawing a ${shape} at (${position.x}, ${position.y})`);
    }

    const startPoint: Point = { x: 10, y: 20 };
    draw('circle', startPoint); // Output: Drawing a circle at (10, 20)
    15.Type Guards with Classes:
    Type guards can also be used with classes to narrow down the type of an object instance.
    class Animal {
    name: string;
    constructor(name: string) {
    this.name = name;
    }
    }

    class Dog extends Animal {
    bark() {
    console.log('Woof!');
    }
    }

    function makeSound(animal: Animal) {
    if (animal instanceof Dog) {
    animal.bark(); // Type: Dog
    } else {
    console.log('Unknown animal');
    }
    }

    const dog = new Dog('Buddy');
    const animal = new Animal('Unknown');

    makeSound(dog); // Output: Woof!
    makeSound(animal); // Output: Unknown animal
    Top comments (6)

    Subscribe
    pic
    Add to the discussion


    vickodev profile image
    Vıɔk A Hıƃnıʇɐ C.
    16 juil.

    Hey bro, great post!!
    A small observation. For point 8 you can use the Partial Type like this:
    interface User {
    id: number;
    name: string;
    email: string;
    }

    type PartialUser = Partial<User>;

    const partialUser: PartialUser = {
    name: "Nikola Tesla",
    email: "nikola@teslaxcorp.com"
    };
    Even, add new properties, for example:
    type MyOwnUser = Partial<User> & { age: number };

    const ownUser: MyOwnUser = {
    name: "Nikola Tesla",
    email: "nikola@teslaxcorp.com",
    age: 27
    };

    15
    likes
    Like
    Reply


    samuel-braun profile image
    Samuel Braun
    16 juil. • Edited on 16 juil.

    Another one I enjoy quiet often is the const assertion. With them you can make stuff readonly outside of class members. For example:

    With as const:
    // Type '"hello"'
    let x = "hello" as const;

    // Type 'readonly [10, 20]'
    let y = [10, 20] as const;

    // Type '{ readonly text: "hello" }'
    let z = { text: "hello" } as const;
    Without as const:
    // Type 'string'
    let x = "hello";

    // Type 'number[]'
    let y = [10, 20];

    // Type '{ text: string }'
    let z = { text: "hello" };