diff --git a/src/index.d.ts b/src/index.d.ts index 1b518ee268..e408ae67cb 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -137,7 +137,8 @@ export { GraphQLWrappingType, GraphQLNullableType, GraphQLNamedType, - Thunk, + ThunkArray, + ThunkObjMap, GraphQLSchemaConfig, GraphQLSchemaExtensions, GraphQLDirectiveConfig, diff --git a/src/index.js b/src/index.js index 5d3be4b8b0..cd446b7fd5 100644 --- a/src/index.js +++ b/src/index.js @@ -136,7 +136,8 @@ export type { GraphQLWrappingType, GraphQLNullableType, GraphQLNamedType, - Thunk, + ThunkArray, + ThunkObjMap, GraphQLSchemaConfig, GraphQLDirectiveConfig, GraphQLArgument, diff --git a/src/jsutils/ObjMap.d.ts b/src/jsutils/ObjMap.d.ts new file mode 100644 index 0000000000..29f31fae66 --- /dev/null +++ b/src/jsutils/ObjMap.d.ts @@ -0,0 +1,7 @@ +export type ObjMap = Record; +export type ObjMapLike = ObjMap | Record; + +export type ReadOnlyObjMap = Readonly>; +export type ReadOnlyObjMapLike = + | Readonly> + | ReadOnlyObjMap; diff --git a/src/type/definition.d.ts b/src/type/definition.d.ts index 69150e727f..2f085c9c8a 100644 --- a/src/type/definition.d.ts +++ b/src/type/definition.d.ts @@ -5,6 +5,7 @@ import { Maybe } from '../jsutils/Maybe'; import { PromiseOrValue } from '../jsutils/PromiseOrValue'; import { Path } from '../jsutils/Path'; +import { ObjMap } from '../jsutils/ObjMap'; import { ScalarTypeDefinitionNode, @@ -263,9 +264,8 @@ export function getNamedType(type: GraphQLType): GraphQLNamedType; * Used while defining GraphQL types to allow for circular references in * otherwise immutable type definitions. */ -export type Thunk> = - | (() => T) - | T; +export type ThunkArray = Array | (() => Array); +export type ThunkObjMap = ObjMap | (() => ObjMap); /** * Custom extensions @@ -435,8 +435,8 @@ export function argsToArgsConfig( export interface GraphQLObjectTypeConfig { name: string; description?: Maybe; - interfaces?: Thunk>; - fields: Thunk>; + interfaces?: ThunkArray; + fields: ThunkObjMap>; isTypeOf?: Maybe>; extensions?: Maybe>>; astNode?: Maybe; @@ -637,8 +637,8 @@ export class GraphQLInterfaceType { export interface GraphQLInterfaceTypeConfig { name: string; description?: Maybe; - interfaces?: Thunk>; - fields: Thunk>; + interfaces?: ThunkArray; + fields: ThunkObjMap>; /** * Optionally provide a custom type resolver function. If one is not provided, * the default implementation will call `isTypeOf` on each implementing @@ -711,7 +711,7 @@ export class GraphQLUnionType { export interface GraphQLUnionTypeConfig { name: string; description?: Maybe; - types: Thunk>; + types: ThunkArray; /** * Optionally provide a custom type resolver function. If one is not provided, * the default implementation will call `isTypeOf` on each implementing @@ -884,7 +884,7 @@ export class GraphQLInputObjectType { export interface GraphQLInputObjectTypeConfig { name: string; description?: Maybe; - fields: Thunk; + fields: ThunkObjMap; extensions?: Maybe>; astNode?: Maybe; extensionASTNodes?: Maybe>; diff --git a/src/type/definition.js b/src/type/definition.js index ed24c7f57a..02fccdd82d 100644 --- a/src/type/definition.js +++ b/src/type/definition.js @@ -511,9 +511,14 @@ export function getNamedType(type) { * Used while defining GraphQL types to allow for circular references in * otherwise immutable type definitions. */ -export type Thunk<+T: ObjMap | Array> = (() => T) | T; +export type ThunkArray = (() => Array) | Array; +export type ThunkObjMap = (() => ObjMap) | ObjMap; -function resolveThunk<+T: ObjMap | Array>(thunk: Thunk): T { +function resolveArrayThunk(thunk: ThunkArray): Array { + return typeof thunk === 'function' ? thunk() : thunk; +} + +function resolveObjMapThunk(thunk: ThunkObjMap): ObjMap { return typeof thunk === 'function' ? thunk() : thunk; } @@ -703,8 +708,8 @@ export class GraphQLObjectType { astNode: ?ObjectTypeDefinitionNode; extensionASTNodes: ?$ReadOnlyArray; - _fields: Thunk>; - _interfaces: Thunk>; + _fields: ThunkObjMap>; + _interfaces: ThunkArray; constructor(config: $ReadOnly>) { this.name = config.name; @@ -771,7 +776,7 @@ function defineInterfaces( | GraphQLInterfaceTypeConfig, >, ): Array { - const interfaces = resolveThunk(config.interfaces ?? []); + const interfaces = resolveArrayThunk(config.interfaces ?? []); devAssert( Array.isArray(interfaces), `${config.name} interfaces must be an Array or a function which returns an Array.`, @@ -785,7 +790,7 @@ function defineFieldMap( | GraphQLInterfaceTypeConfig, >, ): GraphQLFieldMap { - const fieldMap = resolveThunk(config.fields); + const fieldMap = resolveObjMapThunk(config.fields); devAssert( isPlainObj(fieldMap), `${config.name} fields must be an object with field names as keys or a function which returns such an object.`, @@ -874,8 +879,8 @@ export function argsToArgsConfig( export type GraphQLObjectTypeConfig = {| name: string, description?: ?string, - interfaces?: Thunk>, - fields: Thunk>, + interfaces?: ThunkArray, + fields: ThunkObjMap>, isTypeOf?: ?GraphQLIsTypeOfFn, extensions?: ?ReadOnlyObjMapLike, astNode?: ?ObjectTypeDefinitionNode, @@ -1020,8 +1025,8 @@ export class GraphQLInterfaceType { astNode: ?InterfaceTypeDefinitionNode; extensionASTNodes: ?$ReadOnlyArray; - _fields: Thunk>; - _interfaces: Thunk>; + _fields: ThunkObjMap>; + _interfaces: ThunkArray; constructor(config: $ReadOnly>) { this.name = config.name; @@ -1085,8 +1090,8 @@ export class GraphQLInterfaceType { export type GraphQLInterfaceTypeConfig = {| name: string, description?: ?string, - interfaces?: Thunk>, - fields: Thunk>, + interfaces?: ThunkArray, + fields: ThunkObjMap>, /** * Optionally provide a custom type resolver function. If one is not provided, * the default implementation will call `isTypeOf` on each implementing @@ -1137,7 +1142,7 @@ export class GraphQLUnionType { astNode: ?UnionTypeDefinitionNode; extensionASTNodes: ?$ReadOnlyArray; - _types: Thunk>; + _types: ThunkArray; constructor(config: $ReadOnly>) { this.name = config.name; @@ -1192,7 +1197,7 @@ export class GraphQLUnionType { function defineTypes( config: $ReadOnly>, ): Array { - const types = resolveThunk(config.types); + const types = resolveArrayThunk(config.types); devAssert( Array.isArray(types), `Must provide Array of types or a function which returns such an array for Union ${config.name}.`, @@ -1203,7 +1208,7 @@ function defineTypes( export type GraphQLUnionTypeConfig = {| name: string, description?: ?string, - types: Thunk>, + types: ThunkArray, /** * Optionally provide a custom type resolver function. If one is not provided, * the default implementation will call `isTypeOf` on each implementing @@ -1463,7 +1468,7 @@ export class GraphQLInputObjectType { astNode: ?InputObjectTypeDefinitionNode; extensionASTNodes: ?$ReadOnlyArray; - _fields: Thunk; + _fields: ThunkObjMap; constructor(config: $ReadOnly) { this.name = config.name; @@ -1519,7 +1524,7 @@ export class GraphQLInputObjectType { function defineInputFieldMap( config: $ReadOnly, ): GraphQLInputFieldMap { - const fieldMap = resolveThunk(config.fields); + const fieldMap = resolveObjMapThunk(config.fields); devAssert( isPlainObj(fieldMap), `${config.name} fields must be an object with field names as keys or a function which returns such an object.`, @@ -1545,7 +1550,7 @@ function defineInputFieldMap( export type GraphQLInputObjectTypeConfig = {| name: string, description?: ?string, - fields: Thunk, + fields: ThunkObjMap, extensions?: ?ReadOnlyObjMapLike, astNode?: ?InputObjectTypeDefinitionNode, extensionASTNodes?: ?$ReadOnlyArray, diff --git a/src/type/index.d.ts b/src/type/index.d.ts index 9686f413b7..f226df5651 100644 --- a/src/type/index.d.ts +++ b/src/type/index.d.ts @@ -73,7 +73,8 @@ export { GraphQLWrappingType, GraphQLNullableType, GraphQLNamedType, - Thunk, + ThunkArray, + ThunkObjMap, GraphQLArgument, GraphQLArgumentConfig, GraphQLArgumentExtensions, diff --git a/src/type/index.js b/src/type/index.js index 811d50247a..6bcef9daed 100644 --- a/src/type/index.js +++ b/src/type/index.js @@ -128,7 +128,8 @@ export type { GraphQLWrappingType, GraphQLNullableType, GraphQLNamedType, - Thunk, + ThunkArray, + ThunkObjMap, GraphQLArgument, GraphQLArgumentConfig, GraphQLEnumTypeConfig,