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

__element__ incompatible between parent & child types #720

Open
jvassev opened this issue Aug 21, 2023 · 2 comments
Open

__element__ incompatible between parent & child types #720

jvassev opened this issue Aug 21, 2023 · 2 comments

Comments

@jvassev
Copy link

jvassev commented Aug 21, 2023

Code
The code causing the error.

// fetches the configuration for anything that implements HasConfiguration
async function getConfigurationFor(type: e.default.HasConfiguration, ownerId: string): any {
  const found = await e
    .select(type, () => ({
      config: {
        e.default.Configuration.data,
      },
      filter_single: {
        id: ownerId,
      },
    }))
    .run(client);
   return found.config.data
}

// now, when I try to get the configuration for user userId:
const cfg = getConfigurationFor(e.default.User, userId);

// this compilation error occurs:
// Type '$expr_PathNode<TypeSet<$User, Cardinality.Many>, null>' is not assignable to type '$expr_PathNode<TypeSet<$HasConfiguration, Cardinality.Many>, null>'.
//   Type '$expr_PathNode<TypeSet<$User, Cardinality.Many>, null>' is not assignable to type '{ __element__: $HasConfiguration; __cardinality__: Cardinality.Many; __parent__: null; __kind__: ExpressionKind.PathNode; "*": { id: true; }; }'.
//     Types of property '__element__' are incompatible.

Schema

module default {
  type Configuration {
    data: json;
  }

  abstract type HasConfiguration {
    config: Configuration;
  }

  type User extending HasConfiguration {
    email: str;
  }

  type Project extending HasConfiguration {
    name: str;
  }
}

Generated EdgeQL

Error or desired behavior

I think it would be nice to treat EdgeQL subtypes as subtypes in TS code. If I ignore the compiler error from the example above (using getConfigurationFor(e.default.User as any, x) ), the code works.

The error has to do with the __element__ property being different for the parent (HasConfiguration) and child(User or Project);

A solution I could think of is making the __element__s compatible or have a "cast" method, for example:

// here asParent is generated and prepopulated with all the parents of User
// the resulting value has the same __element__ as HasConfiguration
// but 
const cfg = getConfigurationFor(e.default.User.asParent.HasConfiguration, x);

It's like a handle to the User type which lets you only touch the properties inherited from one of its parents.

Versions (please complete the following information):

  • OS:

  • EdgeDB version (e.g. 2.0): edgedb-server, version 3.2+d2023072119.gb7dc55395.cv202305040002.r202307211907.tpa4dmxzwgqwxk3tlnzxxo3rnnruw45lyfvtw45i.bofficial.s99ce519

  • EdgeDB CLI version (e.g. 2.0): EdgeDB CLI 3.4.0+160d07d

  • edgedb-js version (e.g. 0.20.10;): 1.3.4

  • @edgedb/generate version (e.g. 0.0.7;): 0.3.3

  • Typescript version: 5.1.3

  • Node/Deno version: v16.15.0

@scotttrinh
Copy link
Collaborator

This is somewhat related to the work I've started in #606 . It's a little tricky because TypeScript and EdgeQL have slightly different type systems, so I'm trying to tread carefully here. Definitely makes sense from the TypeScript perspective of wanting to define some function that is polymorphic based on some superclass/interface.

@jvassev
Copy link
Author

jvassev commented Aug 22, 2023

Thank you for the quick response!
I tried to find a similar issue but did not discover #606. This is clearly a duplicate of it.

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

No branches or pull requests

2 participants