Skip to content

Commit 6f229f7

Browse files
committed
unions that implement interfaces HAVE fields
1 parent 2f4d7d3 commit 6f229f7

File tree

4 files changed

+46
-14
lines changed

4 files changed

+46
-14
lines changed

src/jsutils/mapValues.ts

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import type { ObjMap, ReadOnlyObjMap } from './ObjMap';
2+
3+
/**
4+
* Creates an object map from an array of `maps` with the same keys as each `map`
5+
* in `maps` and values generated by running each value of `map` thru `fn`.
6+
*/
7+
export function mapValues<T, V>(
8+
maps: ReadonlyArray<ReadOnlyObjMap<T>>,
9+
fn: (value: T, key: string) => V,
10+
): ObjMap<V> {
11+
const result = Object.create(null);
12+
13+
for (const map of maps) {
14+
for (const key of Object.keys(map)) {
15+
result[key] = fn(map[key], key);
16+
}
17+
}
18+
return result;
19+
}

src/type/definition.ts

+15
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { isObjectLike } from '../jsutils/isObjectLike';
77
import { keyMap } from '../jsutils/keyMap';
88
import { keyValMap } from '../jsutils/keyValMap';
99
import { mapValue } from '../jsutils/mapValue';
10+
import { mapValues } from '../jsutils/mapValues';
1011
import type { Maybe } from '../jsutils/Maybe';
1112
import type { ObjMap } from '../jsutils/ObjMap';
1213
import type { Path } from '../jsutils/Path';
@@ -1216,6 +1217,7 @@ export class GraphQLUnionType {
12161217
astNode: Maybe<UnionTypeDefinitionNode>;
12171218
extensionASTNodes: ReadonlyArray<UnionTypeExtensionNode>;
12181219

1220+
private _fields: GraphQLFieldMap<any, any> | undefined;
12191221
private _types: ThunkReadonlyArray<GraphQLObjectType>;
12201222
private _interfaces: ThunkReadonlyArray<GraphQLInterfaceType>;
12211223

@@ -1240,6 +1242,19 @@ export class GraphQLUnionType {
12401242
return 'GraphQLUnionType';
12411243
}
12421244

1245+
getFields(): GraphQLFieldMap<any, any> {
1246+
if (this._fields !== undefined) {
1247+
return this._fields;
1248+
}
1249+
1250+
this._fields = mapValues(
1251+
this.getInterfaces().map((iface) => iface.getFields()),
1252+
identityFunc,
1253+
);
1254+
1255+
return this._fields;
1256+
}
1257+
12431258
getTypes(): ReadonlyArray<GraphQLObjectType> {
12441259
if (typeof this._types === 'function') {
12451260
this._types = this._types();

src/utilities/TypeInfo.ts

+1-11
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,9 @@ import {
2323
isEnumType,
2424
isInputObjectType,
2525
isInputType,
26-
isInterfaceType,
2726
isListType,
2827
isObjectType,
2928
isOutputType,
30-
isUnionType,
3129
} from '../type/definition';
3230
import type { GraphQLDirective } from '../type/directives';
3331
import {
@@ -321,17 +319,9 @@ function getFieldDef(
321319
if (name === TypeNameMetaFieldDef.name && isCompositeType(parentType)) {
322320
return TypeNameMetaFieldDef;
323321
}
324-
if (isObjectType(parentType) || isInterfaceType(parentType)) {
322+
if (isCompositeType(parentType)) {
325323
return parentType.getFields()[name];
326324
}
327-
if (isUnionType(parentType)) {
328-
for (const iface of parentType.getInterfaces()) {
329-
const field = iface.getFields()[name];
330-
if (field) {
331-
return field;
332-
}
333-
}
334-
}
335325
}
336326

337327
/**

src/validation/__tests__/FieldsOnCorrectTypeRule-test.ts

+11-3
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,21 @@ const testSchema = buildSchema(`
4343
4444
union CatOrDog = Cat | Dog
4545
46-
union ConstrainedCatOrDog implements Pet = Cat | Dog
46+
interface Named {
47+
name: String
48+
}
4749
48-
type Human {
50+
type Human implements Named {
4951
name: String
5052
pets: [Pet]
5153
}
5254
55+
type Alien implements Named {
56+
name: String
57+
}
58+
59+
union NamedHumanOrAlien implements Named = Human | Alien
60+
5361
type Query {
5462
human: Human
5563
}
@@ -85,7 +93,7 @@ describe('Validate: Fields on correct type', () => {
8593

8694
it('Union implementing interface field selection', () => {
8795
expectValid(`
88-
fragment unionImplementingInterfaceFieldSelection on ConstrainedCatOrDog {
96+
fragment unionImplementingInterfaceFieldSelection on HumanOrAlien {
8997
__typename
9098
name
9199
}

0 commit comments

Comments
 (0)