Skip to content

Instantly share code, notes, and snippets.

@Mefistophell
Last active July 24, 2024 11:38
Show Gist options
  • Select an option

  • Save Mefistophell/cd2e5679e1e873ba68babe1004194513 to your computer and use it in GitHub Desktop.

Select an option

Save Mefistophell/cd2e5679e1e873ba68babe1004194513 to your computer and use it in GitHub Desktop.

Revisions

  1. Mefistophell renamed this gist Jul 24, 2024. 1 changed file with 30 additions and 20 deletions.
    50 changes: 30 additions & 20 deletions ts_useful_types.ts → ts_useful_features.ts
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,6 @@
    /** NoInfer type */
    /**
    NoInfer type
    */
    function createStreetLight<C extends string>(
    colors: C[],
    defaultColor?: NoInfer<C>,
    @@ -10,9 +12,12 @@ createStreetLight(["red", "yellow", "green"], "blue"); // Error

    /* ************************************************** */

    /** as const */
    // Works with no types referenced or declared.
    // We only needed a single const assertion.
    /**
    as const
    Works with no types referenced or declared.
    We only needed a single const assertion.
    */
    function getShapes() {
    let result = [
    { kind: "circle", radius: 100 },
    @@ -36,8 +41,11 @@ type T0 = Extract<"a" | "b" | "c", "a" | "f">; // a

    /* ************************************************** */

    /** Not-null assertion */
    // Compiled with --strictNullChecks
    /**
    Not-null assertion
    Compiled with --strictNullChecks
    */
    function validateEntity(e?: Entity) {
    // Throw exception if e is null or invalid entity
    }
    @@ -48,7 +56,9 @@ function processEntity(e?: Entity) {

    /* ************************************************** */

    /** Object.groupBy and Map.groupBy */
    /**
    Object.groupBy and Map.groupBy
    */
    const array = [0, 1, 2, 3, 4, 5];
    const myObj = Object.groupBy(array, (num, index) => {
    return num % 2 === 0 ? "even": "odd";
    @@ -69,14 +79,14 @@ myObj.set("odd", [1, 3, 5]);

    /* ************************************************** */

    /** AsyncDisposable and using
    /**
    AsyncDisposable and using
    Sometimes we have a need to do clean-up after our unit completed its job, this can be: deleting of temp files,
    Sometimes we have a need to do clean-up after our unit completed its job, this can be: deleting of temp files,
    closing network connections, free up some memory.
    New keyword `using` applied to a variable gets its Symbol.dispose or Symbol.asyncDispose method
    New keyword `using` applied to a variable gets its Symbol.dispose or Symbol.asyncDispose method
    to be called at the end of the scope.
    */

    async function doWork() {
    @@ -114,16 +124,16 @@ func();
    // Disposing (async) b
    // Disposing (async) a

    /** DisposableStack and using
    /**
    DisposableStack and using
    useful for doing both one-off clean-up, along with arbitrary amounts of cleanup.
    useful for doing both one-off clean-up, along with arbitrary amounts of cleanup.
    A DisposableStack is a Disposable object that has several methods for keeping track of Disposable objects,
    A DisposableStack is a Disposable object that has several methods for keeping track of Disposable objects,
    and can be given functions for doing arbitrary clean-up work.
    Method defer has a callback that will be called once cleanup is disposed.
    Once a resource is created is should be disposed.
    Method defer has a callback that will be called once cleanup is disposed.
    Once a resource is created is should be disposed.
    */
    function doSomeWork() {
    const path = ".some_temp_file";
    @@ -142,7 +152,7 @@ function doSomeWork() {
    }

    /**
    Decorator metadata:
    Exampe of this is here:
    https://gist.github.com/Mefistophell/07d63b44d69d38af9406bc59a35c3ec7
    Decorator metadata:
    Exampe of this is here:
    https://gist.github.com/Mefistophell/07d63b44d69d38af9406bc59a35c3ec7
    */
  2. Mefistophell revised this gist Jul 24, 2024. 1 changed file with 2 additions and 4 deletions.
    6 changes: 2 additions & 4 deletions ts_useful_types.ts
    Original file line number Diff line number Diff line change
    @@ -142,9 +142,7 @@ function doSomeWork() {
    }

    /**
    Decorators metadata
    Decorator metadata:
    Exampe of this is here:
    !(ts-decorator-metadata)[https://gist.github.com/Mefistophell/07d63b44d69d38af9406bc59a35c3ec7]
    https://gist.github.com/Mefistophell/07d63b44d69d38af9406bc59a35c3ec7
    */
  3. Mefistophell revised this gist Jul 24, 2024. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions ts_useful_types.ts
    Original file line number Diff line number Diff line change
    @@ -141,10 +141,10 @@ function doSomeWork() {
    // ...
    }

    /*
    /**
    Decorators metadata
    Exampe of this is here:
    !(ts-decorator-metadata)[https://gist.github.com/Mefistophell/07d63b44d69d38af9406bc59a35c3ec7]
    /*
    */
  4. Mefistophell revised this gist Jul 24, 2024. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion ts_useful_types.ts
    Original file line number Diff line number Diff line change
    @@ -145,4 +145,6 @@ function doSomeWork() {
    Decorators metadata
    Exampe of this is here:

    !(ts-decorator-metadata)[https://gist.github.com/Mefistophell/07d63b44d69d38af9406bc59a35c3ec7]
    !(ts-decorator-metadata)[https://gist.github.com/Mefistophell/07d63b44d69d38af9406bc59a35c3ec7]

    /*
  5. Mefistophell revised this gist Jul 24, 2024. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion ts_useful_types.ts
    Original file line number Diff line number Diff line change
    @@ -144,4 +144,5 @@ function doSomeWork() {
    /*
    Decorators metadata
    Exampe of this is here:
    https://www.typescriptlang.org/play/?#code/PTAEEEDsHsBcAsCmAnUB3AhgT1ASwM6izSgCu+ioAxtJPrKBcrhgDa4BeGARq4oQF5QAZSwBbbtFYAKAJQBuAFA06DJi3Zde-UEMiI0oAOqIMAawCyGAA4AeaNwBWiKrAA0jWM0gBzANoAugB8ckqKsFjWlADCtLCIAB4MAoqgaaAAPqDRrBj4+OBUVPz40MgAIi5lGMTIsZDxSanpWTl5+ADiiLDxFVXINWX1jbDNaa25+QBiuIisACaVNAO1w4mj6aBhAGakkK64tIwoGpyI0gD6sBjIPt0AXKAYkFgeKiOPa0myjwBu0Lh5qAAN5jPDbUDSd7rAB09BquComSy0KSMOszF+NUQshBYM2CGQ0EM+kMAFFkETkNIAETRZ6gWisHDqNhnUDWUi8RF4VTPYqgMSICQofAwmmyMEAXzBuAh0giUWgENRsBhkAwQtAAEIBEIafRvD4JXjNgT4ESSQZQBSqbT6ZBGZBmcdmGyOJRDbhfByiVFkLBZmKJUpNjKwSBwSJxJJWGQKPNHip6L7oNYAHKanRCKFxWFC67zGoYPyszQ8Pj4AJPQhe3yBTJkSDzRDbb2Iea4gD8XaEgTCmz4DAxaczQsErtOWkrMLusFzDXz3QwReuyJBUoUsvlI4zWcEeqbLbb+k7prNaTLnAr-Dh3QXIxhBZXxfXwKlHl3Y+zoECW7DYJfvu6LkPAD6whqQpbjKuz7IGRyOKUkBylg0jevC+yII8DjOK4PyeEa55pBGYAAAKwPgAC0uA+DAyCUGCyYMM+q4YLovIYcUMJMcgpCuGUfiiBIUhPsurEBAO6SRnK0bCXG5AdkmtApkB47sSxxZdjCpYnO6N5VjWBHev41ZZHsx7tvMobpExqZ7mpQgaWuABkzmTnp2hinO0hORg-7pDJ0jaqp-C4qCF5pISxKgKSNqUmUtLpiQQoisghBiDcZgduguAIKApFXh64r+WkMqbLZ1gYLgyDCF4xkTiFYoZdY0jSFlWCPHWPi4gIQREWatmGgA0ogOBCAAUsIADy6ZwnVvgoW1o0lQNylqF4ABqbCkJQE3TbNXWLWhfKYYZzxYLIfjtQEK2bPRsCkMgjoAAYACTAsNo1So872GltrA7VKz3WaVK33Y9L3AqA72VdVtVGmKjgApAtIeBKUqgEDSjhsokyEAACqKRzhekbZpbA36dfNPgg6AkwU1mVNGpJaQFbpmiIGCGB3I8kCkKlihgmzboc2Cc6gLsrCsN+cj9Xd3QQ6Ab3AggBAwmT9Dfhj72q2K9Na8D0pgsQk0zbLJMXuDT2gIhtCLbrkoAeVa28fx1IawzQpM8ZHj64zRm+B43NYTF-PcCgYX4ukuvq9VmtZuxHvflHkXwGrftakIGecxFRBp2KwfscHRvhhVROOno1qE2ltDSAA5OA7DFHXHh18IyosC3oAACySsoylSIgMKsNAPjSP6SEwib+1yLIQA

    !(ts-decorator-metadata)[https://gist.github.com/Mefistophell/07d63b44d69d38af9406bc59a35c3ec7]
  6. Mefistophell revised this gist Jul 24, 2024. 1 changed file with 6 additions and 1 deletion.
    7 changes: 6 additions & 1 deletion ts_useful_types.ts
    Original file line number Diff line number Diff line change
    @@ -139,4 +139,9 @@ function doSomeWork() {
    return;
    }
    // ...
    }
    }

    /*
    Decorators metadata
    Exampe of this is here:
    https://www.typescriptlang.org/play/?#code/PTAEEEDsHsBcAsCmAnUB3AhgT1ASwM6izSgCu+ioAxtJPrKBcrhgDa4BeGARq4oQF5QAZSwBbbtFYAKAJQBuAFA06DJi3Zde-UEMiI0oAOqIMAawCyGAA4AeaNwBWiKrAA0jWM0gBzANoAugB8ckqKsFjWlADCtLCIAB4MAoqgaaAAPqDRrBj4+OBUVPz40MgAIi5lGMTIsZDxSanpWTl5+ADiiLDxFVXINWX1jbDNaa25+QBiuIisACaVNAO1w4mj6aBhAGakkK64tIwoGpyI0gD6sBjIPt0AXKAYkFgeKiOPa0myjwBu0Lh5qAAN5jPDbUDSd7rAB09BquComSy0KSMOszF+NUQshBYM2CGQ0EM+kMAFFkETkNIAETRZ6gWisHDqNhnUDWUi8RF4VTPYqgMSICQofAwmmyMEAXzBuAh0giUWgENRsBhkAwQtAAEIBEIafRvD4JXjNgT4ESSQZQBSqbT6ZBGZBmcdmGyOJRDbhfByiVFkLBZmKJUpNjKwSBwSJxJJWGQKPNHip6L7oNYAHKanRCKFxWFC67zGoYPyszQ8Pj4AJPQhe3yBTJkSDzRDbb2Iea4gD8XaEgTCmz4DAxaczQsErtOWkrMLusFzDXz3QwReuyJBUoUsvlI4zWcEeqbLbb+k7prNaTLnAr-Dh3QXIxhBZXxfXwKlHl3Y+zoECW7DYJfvu6LkPAD6whqQpbjKuz7IGRyOKUkBylg0jevC+yII8DjOK4PyeEa55pBGYAAAKwPgAC0uA+DAyCUGCyYMM+q4YLovIYcUMJMcgpCuGUfiiBIUhPsurEBAO6SRnK0bCXG5AdkmtApkB47sSxxZdjCpYnO6N5VjWBHev41ZZHsx7tvMobpExqZ7mpQgaWuABkzmTnp2hinO0hORg-7pDJ0jaqp-C4qCF5pISxKgKSNqUmUtLpiQQoisghBiDcZgduguAIKApFXh64r+WkMqbLZ1gYLgyDCF4xkTiFYoZdY0jSFlWCPHWPi4gIQREWatmGgA0ogOBCAAUsIADy6ZwnVvgoW1o0lQNylqF4ABqbCkJQE3TbNXWLWhfKYYZzxYLIfjtQEK2bPRsCkMgjoAAYACTAsNo1So872GltrA7VKz3WaVK33Y9L3AqA72VdVtVGmKjgApAtIeBKUqgEDSjhsokyEAACqKRzhekbZpbA36dfNPgg6AkwU1mVNGpJaQFbpmiIGCGB3I8kCkKlihgmzboc2Cc6gLsrCsN+cj9Xd3QQ6Ab3AggBAwmT9Dfhj72q2K9Na8D0pgsQk0zbLJMXuDT2gIhtCLbrkoAeVa28fx1IawzQpM8ZHj64zRm+B43NYTF-PcCgYX4ukuvq9VmtZuxHvflHkXwGrftakIGecxFRBp2KwfscHRvhhVROOno1qE2ltDSAA5OA7DFHXHh18IyosC3oAACySsoylSIgMKsNAPjSP6SEwib+1yLIQA
  7. Mefistophell revised this gist Jul 24, 2024. 1 changed file with 11 additions and 1 deletion.
    12 changes: 11 additions & 1 deletion ts_useful_types.ts
    Original file line number Diff line number Diff line change
    @@ -114,7 +114,17 @@ func();
    // Disposing (async) b
    // Disposing (async) a

    /** DisposableStack and using */
    /** DisposableStack and using
    useful for doing both one-off clean-up, along with arbitrary amounts of cleanup.
    A DisposableStack is a Disposable object that has several methods for keeping track of Disposable objects,
    and can be given functions for doing arbitrary clean-up work.
    Method defer has a callback that will be called once cleanup is disposed.
    Once a resource is created is should be disposed.
    */
    function doSomeWork() {
    const path = ".some_temp_file";
    const file = fs.openSync(path, "w+");
  8. Mefistophell revised this gist Jul 24, 2024. 1 changed file with 10 additions and 1 deletion.
    11 changes: 10 additions & 1 deletion ts_useful_types.ts
    Original file line number Diff line number Diff line change
    @@ -69,7 +69,16 @@ myObj.set("odd", [1, 3, 5]);

    /* ************************************************** */

    /** AsyncDisposable and using */
    /** AsyncDisposable and using
    Sometimes we have a need to do clean-up after our unit completed its job, this can be: deleting of temp files,
    closing network connections, free up some memory.
    New keyword `using` applied to a variable gets its Symbol.dispose or Symbol.asyncDispose method
    to be called at the end of the scope.
    */

    async function doWork() {
    // Do fake work for half a second.
    await new Promise(resolve => setTimeout(resolve, 500));
  9. Mefistophell revised this gist Jul 11, 2024. 1 changed file with 54 additions and 1 deletion.
    55 changes: 54 additions & 1 deletion ts_useful_types.ts
    Original file line number Diff line number Diff line change
    @@ -67,4 +67,57 @@ const myObj = new Map();
    myObj.set("even", [0, 2, 4]);
    myObj.set("odd", [1, 3, 5]);

    /* ************************************************** */
    /* ************************************************** */

    /** AsyncDisposable and using */
    async function doWork() {
    // Do fake work for half a second.
    await new Promise(resolve => setTimeout(resolve, 500));
    }
    function loggy(id: string): AsyncDisposable {
    console.log(`Constructing ${id}`);
    return {
    async [Symbol.asyncDispose]() {
    console.log(`Disposing (async) ${id}`);
    await doWork();
    },
    }
    }
    async function func() {
    await using a = loggy("a");
    await using b = loggy("b");
    {
    await using c = loggy("c");
    await using d = loggy("d");
    }
    await using e = loggy("e");
    return;
    }
    func();
    // Constructing a
    // Constructing b
    // Constructing c
    // Constructing d
    // Disposing (async) d
    // Disposing (async) c
    // Constructing e
    // Disposing (async) e
    // Disposing (async) b
    // Disposing (async) a

    /** DisposableStack and using */
    function doSomeWork() {
    const path = ".some_temp_file";
    const file = fs.openSync(path, "w+");
    using cleanup = new DisposableStack();
    cleanup.defer(() => {
    fs.closeSync(file);
    fs.unlinkSync(path);
    });
    // use file...
    if (someCondition()) {
    // do some more work...
    return;
    }
    // ...
    }
  10. Mefistophell revised this gist Jul 11, 2024. 1 changed file with 26 additions and 1 deletion.
    27 changes: 26 additions & 1 deletion ts_useful_types.ts
    Original file line number Diff line number Diff line change
    @@ -8,6 +8,7 @@ function createStreetLight<C extends string>(
    createStreetLight(["red", "yellow", "green"], "red"); // OK
    createStreetLight(["red", "yellow", "green"], "blue"); // Error

    /* ************************************************** */

    /** as const */
    // Works with no types referenced or declared.
    @@ -33,6 +34,7 @@ type T0 = NonNullable<string | number | undefined>; // string | number
    type T0 = ReturnType<() => string>; // string
    type T0 = Extract<"a" | "b" | "c", "a" | "f">; // a

    /* ************************************************** */

    /** Not-null assertion */
    // Compiled with --strictNullChecks
    @@ -42,4 +44,27 @@ function validateEntity(e?: Entity) {
    function processEntity(e?: Entity) {
    validateEntity(e);
    let s = e!.name; // Assert that e is non-null and access name
    }
    }

    /* ************************************************** */

    /** Object.groupBy and Map.groupBy */
    const array = [0, 1, 2, 3, 4, 5];
    const myObj = Object.groupBy(array, (num, index) => {
    return num % 2 === 0 ? "even": "odd";
    });
    // equivalent to
    const myObj = {
    even: [0, 2, 4],
    odd: [1, 3, 5],
    };

    const myObj = Map.groupBy(array, (num, index) => {
    return num % 2 === 0 ? "even" : "odd";
    });
    // equivalent to
    const myObj = new Map();
    myObj.set("even", [0, 2, 4]);
    myObj.set("odd", [1, 3, 5]);

    /* ************************************************** */
  11. Mefistophell revised this gist Jul 8, 2024. 1 changed file with 12 additions and 1 deletion.
    13 changes: 12 additions & 1 deletion ts_useful_types.ts
    Original file line number Diff line number Diff line change
    @@ -31,4 +31,15 @@ for (const shape of getShapes()) {

    type T0 = NonNullable<string | number | undefined>; // string | number
    type T0 = ReturnType<() => string>; // string
    type T0 = Extract<"a" | "b" | "c", "a" | "f">; // a
    type T0 = Extract<"a" | "b" | "c", "a" | "f">; // a


    /** Not-null assertion */
    // Compiled with --strictNullChecks
    function validateEntity(e?: Entity) {
    // Throw exception if e is null or invalid entity
    }
    function processEntity(e?: Entity) {
    validateEntity(e);
    let s = e!.name; // Assert that e is non-null and access name
    }
  12. Mefistophell renamed this gist Jul 8, 2024. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  13. Mefistophell created this gist Jul 8, 2024.
    34 changes: 34 additions & 0 deletions example.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,34 @@
    /** NoInfer type */
    function createStreetLight<C extends string>(
    colors: C[],
    defaultColor?: NoInfer<C>,
    ) {
    // ...
    }
    createStreetLight(["red", "yellow", "green"], "red"); // OK
    createStreetLight(["red", "yellow", "green"], "blue"); // Error


    /** as const */
    // Works with no types referenced or declared.
    // We only needed a single const assertion.
    function getShapes() {
    let result = [
    { kind: "circle", radius: 100 },
    { kind: "square", sideLength: 50 },
    ] as const;
    return result;
    }
    for (const shape of getShapes()) {
    // Narrows perfectly!
    if (shape.kind === "circle") {
    console.log("Circle radius", shape.radius);
    } else {
    console.log("Square side length", shape.sideLength);
    }
    }


    type T0 = NonNullable<string | number | undefined>; // string | number
    type T0 = ReturnType<() => string>; // string
    type T0 = Extract<"a" | "b" | "c", "a" | "f">; // a