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

Can not define an interface with a field that is then specialised as an enum field. #4869

Open
TikiTDO opened this issue Dec 14, 2024 · 1 comment

Comments

@TikiTDO
Copy link

TikiTDO commented Dec 14, 2024

In previous versions of relay it was possible to define interfaces that defined a String! field, and that field could then be specialized to an enum object the implemented this interface, such that the compiler would treat the specialized value as a sub-type of the String!. For example, I could define this interface:

interface StatusChangeable { 
  status: String! 
  allowedActions: [String!]!
}

And then use it as follows:

enum UserStatus {
  active
  banned
  inactive
}

type User implements StatusChangeable {
  status: UserStatus!
}

This way any code that used the User type directly could be typed properly to handle the specific values that User supports, while code that cared only about the StatusChangeable didn't have to concern itself with the specialized values.

It would be great if I could define the interface StatusChangeable with either a generic String! status, or even more ideally, with an enum that is a super-set of the specialized enum, such as:

enum AllStatuses {
  active
  banned
  inactive
  other
  statuses
  here
}

Otherwise the only option is to update all the types that implement StatusChangeable to define status as a String! which loses all the specificity and type-safety, or to avoid using an interface which can create a lot of duplicate code that could easily be prevented with an single interface.

If is_named_type_subtype_of handled the Enum subset scenario, this could be done fairly easily:

        (Type::Enum(sub_id), Type::Enum(super_id)) => {
            let sub_enum = self.enum_(sub_id);
            let super_enum = self.enum_(super_id);
            // Ensure all values in the sub enum are present in the super enum
            sub_enum.values.iter().all(|sub_value| {
                super_enum.values.iter().any(|super_value| super_value.value == sub_value.value)
            })
        }

If this approach is acceptable I can submit a PR.

@captbaritone
Copy link
Contributor

Thanks for the report. My reading of the GraphQL Spec is that enums are not considered a sub type of string for the purposes of fields:

Our goal here should be to match the GraphQL spec, so unless I am misreading the spec (always possible!) I think we'd pass on going back to the old behavior. Let me know if I've missed something.

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