Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate user-defined type guards #40

Open
christianlavoie opened this issue Nov 28, 2023 · 6 comments
Open

Generate user-defined type guards #40

christianlavoie opened this issue Nov 28, 2023 · 6 comments

Comments

@christianlavoie
Copy link

In cases where a sum type is transcribed as a series of interfaces and a union type:

export type U = A | B | C;

export interface A {
  tag: "A";
  contents: ...
}

export interface B {
  tag: "B";
  contents: ...
}

export interface C {
  tag: "C";
  contents: ...
}

Type predicates (https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates) would be useful:

function isA(u: A | B | C): U is A {
    return (u as A).tag == "A";
}
@thomasjm
Copy link
Contributor

Interesting idea. In my experience, TypeScript understands discriminated unions perfectly well without explicit type guards. I.e.

if (u.tag === "A") {
  // Now TSC knows u is an A
}

I have no real objection to this feature, though it would only make sense with the ExportEach export mode (for making TS modules, not d.ts files).

I'd be curious about when you'd want this over the normal u.tag === "A" kind of test? If it's just a style thing, I personally wouldn't want to turn it on for all interfaces and bloat my declaration files with lots of boilerplate isX functions...

@christianlavoie
Copy link
Author

I have no real objection to this feature, though it would only make sense with the ExportEach export mode (for making TS modules, not d.ts files).

Indeed.

I'd be curious about when you'd want this over the normal u.tag === "A" kind of test?

Partially stylistic, partially I triggered a bug where one of the checkers I'm using is complaining that u.tag is not defined on U.

If it's just a style thing, I personally wouldn't want to turn it on for all interfaces and bloat my declaration files with lots of boilerplate isX functions...

I'd expect it to be optional.

@thomasjm
Copy link
Contributor

Huh, what checker?

I'd expect it to be optional.

As in, on a per-type basis? Perhaps opted into in the deriveTypeScript' call with ExtraTypeScriptOptions?

@christianlavoie
Copy link
Author

Quoth the relevant package.json:

 "svelte-check": "^3.6.2",

And yeah, ExtraTypeScriptOptions is what makes the most sense to me.

@thomasjm
Copy link
Contributor

A few more notes:

Seems to be something the Svelte community is working on: sveltejs/svelte#9130

After further thought, adding formatting-type options in the ExtraTypeScriptOptions isn't something we're really set up to do. Piping such an option through as a TSDeclaration is probably more invasive than we'd want for such a niche feature.

Another alternative would be to do it at the formatting level, by adding an option to FormattingOptions and then using formatTSDeclarations' with that option for the types you want to do this with.

If you need this immediately, I'd recommend using the TSDeclaration constructors from Data.Aeson.TypeScript.Internal and looping over the return value of getTypeScriptDeclarations yourself to generate the functions you need. You can use the TSRawDeclaration escape hatch to add these to the normal declarations.

@christianlavoie
Copy link
Author

If you need this immediately, I'd recommend using the TSDeclaration constructors from Data.Aeson.TypeScript.Internal and looping over the return value of getTypeScriptDeclarations yourself to generate the functions you need. You can use the TSRawDeclaration escape hatch to add these to the normal declarations.

At this point I'm using ts-auto-guard as a workaround, but it's shoving more stuff in the CI pipeline and I'd much rather do it at the source than as another step in CI.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants