Skip to content

Commit 552e05f

Browse files
committed
feat(object-types): support implementing multi-inherited interface
1 parent 158bfe5 commit 552e05f

File tree

4 files changed

+83
-5
lines changed

4 files changed

+83
-5
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
- support disabling inferring default values (#793)
1313
- support readonly arrays for roles of `@Authorized` decorator (#935)
1414
- add sync version of `buildTypeDefsAndResolvers` function (#803)
15+
- lift restriction of listing all interfaces from inheritance chain in `implements` option of `@ObjectType` decorator (#1435)
1516
### Fixes
1617
- **Breaking Change**: properly emit types nullability when `defaultValue` is provided and remove `ConflictingDefaultWithNullableError` error (#751)
1718
- allow defining extension on field resolver level for fields also defined as a property of the class (#776)

docs/interfaces.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,10 @@ class Person extends Node {
8080
}
8181
```
8282

83-
Also, when we implement the interface that already implements other interface, we need to put them all in `implements` array in `@ObjectType` decorator option, e.g.:
83+
Also, when we implement the interface that already implements other interface, there's no need to put them all in `implements` array in `@ObjectType` decorator option - only the closest one in the inheritance chain is required, e.g.:
8484

8585
```typescript
86-
@ObjectType({ implements: [Person, Node] })
86+
@ObjectType({ implements: [Person] })
8787
class Student extends Person {
8888
@Field()
8989
universityName: string;

src/schema/schema-generator.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -246,9 +246,9 @@ export abstract class SchemaGenerator {
246246
const objectSuperClass = Object.getPrototypeOf(objectType.target);
247247
const hasExtended = objectSuperClass.prototype !== undefined;
248248
const getSuperClassType = () => {
249-
const superClassTypeInfo = this.objectTypesInfo.find(
250-
type => type.target === objectSuperClass,
251-
);
249+
const superClassTypeInfo =
250+
this.objectTypesInfo.find(type => type.target === objectSuperClass) ??
251+
this.interfaceTypesInfo.find(type => type.target === objectSuperClass);
252252
return superClassTypeInfo ? superClassTypeInfo.type : undefined;
253253
};
254254
const interfaceClasses = objectType.interfaceClasses || [];
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import "reflect-metadata";
2+
import { GraphQLSchema, printSchema } from "graphql";
3+
import { Field, InterfaceType, ObjectType, Query, Resolver } from "../../src";
4+
5+
import { getSchemaInfo } from "../helpers/getSchemaInfo";
6+
7+
describe("nested interface inheritance", () => {
8+
let schema: GraphQLSchema;
9+
beforeAll(async () => {
10+
@InterfaceType()
11+
abstract class A {
12+
@Field()
13+
a!: string;
14+
}
15+
16+
@InterfaceType({ implements: A })
17+
abstract class B extends A {
18+
@Field()
19+
b!: string;
20+
}
21+
22+
@InterfaceType({ implements: B })
23+
abstract class C extends B {
24+
@Field()
25+
c!: string;
26+
}
27+
28+
@ObjectType({ implements: C })
29+
class D extends C {
30+
@Field()
31+
d!: string;
32+
}
33+
34+
@Resolver()
35+
class TestResolver {
36+
@Query()
37+
testQuery(): string {
38+
return "testQuery";
39+
}
40+
}
41+
const schemaInfo = await getSchemaInfo({
42+
resolvers: [TestResolver],
43+
orphanedTypes: [A, B, C, D],
44+
});
45+
schema = schemaInfo.schema;
46+
});
47+
48+
it("should properly generate object type, implementing multi-inherited interface, with only one `implements`", async () => {
49+
expect(printSchema(schema)).toMatchInlineSnapshot(`
50+
"type D implements C & B & A {
51+
a: String!
52+
b: String!
53+
c: String!
54+
d: String!
55+
}
56+
57+
interface A {
58+
a: String!
59+
}
60+
61+
interface B implements A {
62+
a: String!
63+
b: String!
64+
}
65+
66+
interface C implements B & A {
67+
a: String!
68+
b: String!
69+
c: String!
70+
}
71+
72+
type Query {
73+
testQuery: String!
74+
}"
75+
`);
76+
});
77+
});

0 commit comments

Comments
 (0)