Skip to content

Instantly share code, notes, and snippets.

@pesterhazy
Last active August 12, 2025 11:03
Show Gist options
  • Save pesterhazy/444e51b4b52a06661c8402ff9ee4959c to your computer and use it in GitHub Desktop.
Save pesterhazy/444e51b4b52a06661c8402ff9ee4959c to your computer and use it in GitHub Desktop.

Revisions

  1. pesterhazy revised this gist Aug 12, 2025. No changes.
  2. pesterhazy revised this gist Aug 7, 2025. 1 changed file with 5 additions and 0 deletions.
    5 changes: 5 additions & 0 deletions typescript-interface-wat.ts
    Original file line number Diff line number Diff line change
    @@ -26,3 +26,8 @@ test.only("experiment 2", async () => {
    experiment = new Experiment();
    experiment.foo({}); // oops, we called foo without passing bar, causing a runtime error
    });

    /*
    How do I change the code so that I can be sure that every class that implements IExperiment
    is safe to use with through the interface?
    */
  3. pesterhazy revised this gist Aug 7, 2025. 1 changed file with 5 additions and 2 deletions.
    7 changes: 5 additions & 2 deletions typescript-interface-wat.ts
    Original file line number Diff line number Diff line change
    @@ -6,9 +6,12 @@ interface IExperiment {
    }

    class Experiment implements IExperiment {
    // Why does Experiment implement IExperiment, even though IExperiment.foo doesn't
    // guarantee that opts.bar is defined?
    // Wat?!
    // Why is Experiment allowed to implement IExperiment (the typechecker doesn't complain)
    // even though IExperiment.foo doesn't guarantee that opts.bar is defined?

    foo(opts: { bar: string }): void {
    // foo needs opts.bar to be there
    assert.ok(opts.bar);
    }
    }
  4. pesterhazy created this gist Aug 7, 2025.
    25 changes: 25 additions & 0 deletions typescript-interface-wat.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,25 @@
    import test from "node:test";
    import assert from "node:assert";

    interface IExperiment {
    foo(opts: {}): void;
    }

    class Experiment implements IExperiment {
    // Why does Experiment implement IExperiment, even though IExperiment.foo doesn't
    // guarantee that opts.bar is defined?
    foo(opts: { bar: string }): void {
    assert.ok(opts.bar);
    }
    }

    test.only("experiment", async () => {
    const experiment = new Experiment();
    experiment.foo({ bar: "baz" });
    });

    test.only("experiment 2", async () => {
    let experiment: IExperiment;
    experiment = new Experiment();
    experiment.foo({}); // oops, we called foo without passing bar, causing a runtime error
    });