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

Support "extends" and intersection operator. #2

Open
vedantroy opened this issue May 18, 2020 · 19 comments
Open

Support "extends" and intersection operator. #2

vedantroy opened this issue May 18, 2020 · 19 comments
Labels
help wanted Extra attention is needed

Comments

@vedantroy
Copy link
Owner

Support

type A = B & C;

and

interface Foo extends Bar {}
@vedantroy vedantroy added the help wanted Extra attention is needed label May 18, 2020
@lukasluecke
Copy link

lukasluecke commented May 20, 2020

This (and basic mapped types, like Record) is the main issue that prevents me from using this to it's full potential in a project that uses intersection types a lot (as I have to duplicate / manually "intersect" the types to validate right now, which kinda defeats the purpose.. 😅)

Is there anything specific you're looking for help with?

@vedantroy
Copy link
Owner Author

I'm just finished a big refactor that will allow me to implement type intersection + other features.

Quick question: With the types you are intersecting, are they both in the same file?

@lukasluecke
Copy link

I saw your commits, looking forward to the next version 🙂 For now I've restructured the parts that I typecheck to all be in the same file and without any intersections or mapped types, but of course it would be a lot nicer to be as flexible as possible with the locations and separations 😉

@vedantroy
Copy link
Owner Author

So the reason I asked about the types being in different files was because I just realized I can't validate multi-file types (Foo imports Bar from another file) using just a macro.

As such, I am trying to figure out if this is a big issue for users. If it is, I will build a CLI tool that can handle multi-file types.

@lukasluecke
Copy link

Mh.. not sure how big of a problem that would be. Would registering the imported type / creating a separate validator in the source file help at all? (is there a way to "connect" these afterwards?)

I think it would probably be fine in most cases for now, seeing as in most cases you could just move the types to where the validation is created, and then import it in the other files from there instead. What about "library" types (something like Record), would these also be affected the same way?

@vedantroy
Copy link
Owner Author

vedantroy commented May 22, 2020

The fundamental issue is that Babel processes files one at a time. So I cannot wait until all files have been processed to build a global "namespace" of types.

The original idea was as you are describing: "register" the imported type in the source file. However, this doesn't work reliably because if the file with the exported type/the register call is processed after the file that consumes the registered/exported type, the macro will throw an error.

Library types won't be affected because I can just hardcode library types like Set, Map, Record into the macro. (Infact, this is what I already do).

Another thing you can do is, instead of moving your types to where you want to generate your validation functions, just generate your validation functions where you declare your types and export them. This works because validation functions are just normal Javascript that can be imported/exported like anything else.

@schontz
Copy link

schontz commented Oct 2, 2020

What is the status of this issue? Assuming I have all my types in the same file...

@vedantroy
Copy link
Owner Author

@schontz Intersection is supported. extends is not supported, but I don't think it would be too bad to support it.

Let me know if "extends" support is important!

@schontz
Copy link

schontz commented Oct 2, 2020

For my uses, yes, I use extends all over the place. Is any form of extends supported?

@vedantroy
Copy link
Owner Author

Hmm, right now no. I'll take a shot at implementing this -- it seems like the extends algorithm is simpler than intersection anyway.

In the meantime, intersection is a pretty viable alternative. It covers pretty much everything extends does I think.

@schontz
Copy link

schontz commented Oct 2, 2020

So just convert

interface Foo extends Bar {
  id: string;
}

to:

type Foo = Bar & {
  id: string;
}

Like that?

@vedantroy
Copy link
Owner Author

Yes, that should work.

@schontz
Copy link

schontz commented Oct 2, 2020

OK. But what if I have generics? For example:

interface Foo<E extends string> {
  data: E;
}

interface Bar extends Foo<'bar'> {}

const bar: Bar = { data: 'foo' }; // error
const bar2: Bar = { data: 'bar' }; // good

@vedantroy
Copy link
Owner Author

vedantroy commented Oct 2, 2020

I believe intersection can cover everything extends does.

The above example would become:

interface Foo<E extends string> {
    data : E
}

type Bar = Foo<'bar'>

There's no intersection involved because the body of the Bar interface is empty.

If the body of the interface wasn't empty (let's say it was: data2: Q, where Q is another generic parameter) then you would do

type Bar<Q> = Foo<'bar'> & { data2: Q }

@schontz
Copy link

schontz commented Oct 2, 2020

Ok great. I'll see if I can get this to work. Thanks for all your help.

E extends string doesn't cause any issues?

@vedantroy
Copy link
Owner Author

Hm, I should check that it doesn't. If it does -- I can fix that pretty quickly, since upper bound at types are compile time constraints that are not relevant at runtime.

@schontz
Copy link

schontz commented Oct 2, 2020

OK. No big deal, because I control enough of my code that I can drop E extends string. If I make E a number, shame on me!

@vedantroy
Copy link
Owner Author

Just tested -- the E extends string inside of the type parameter is supported.

@schontz
Copy link

schontz commented Oct 2, 2020

This is great. Looking forward to playing with this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

3 participants