facebook / facebook/relay

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

Open
#4,869 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
19k
Forks
1.9k
PR merge metrics
No merged PRs in 30d

Description

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](https://github.com/facebook/relay/blob/1e60e4716a5e6dccbba4c1c23a83a296b3b28542/compiler/crates/schema/src/graphql_schema.rs#L160) 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.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.