Last active
August 12, 2025 11:03
-
-
Save pesterhazy/444e51b4b52a06661c8402ff9ee4959c to your computer and use it in GitHub Desktop.
typescript interface unsoundness wat
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import test from "node:test"; | |
| import assert from "node:assert"; | |
| interface IExperiment { | |
| foo(opts: {}): void; | |
| } | |
| class Experiment implements IExperiment { | |
| // 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); | |
| } | |
| } | |
| 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 | |
| }); | |
| /* | |
| 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? | |
| */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks to Matt Pollock for pointing me in the right direction https://bsky.app/profile/mattpocock.com