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

feat(scalar): add generics to scalars #1522

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
28 changes: 14 additions & 14 deletions src/execution/execute.js
Expand Up @@ -423,7 +423,7 @@ function executeOperation(
*/
function executeFieldsSerially(
exeContext: ExecutionContext,
parentType: GraphQLObjectType,
parentType: GraphQLObjectType<*, *>,
sourceValue: mixed,
path: ResponsePath | void,
fields: ObjMap<Array<FieldNode>>,
Expand Down Expand Up @@ -462,7 +462,7 @@ function executeFieldsSerially(
*/
function executeFields(
exeContext: ExecutionContext,
parentType: GraphQLObjectType,
parentType: GraphQLObjectType<*, *>,
sourceValue: mixed,
path: ResponsePath | void,
fields: ObjMap<Array<FieldNode>>,
Expand Down Expand Up @@ -511,7 +511,7 @@ function executeFields(
*/
export function collectFields(
exeContext: ExecutionContext,
runtimeType: GraphQLObjectType,
runtimeType: GraphQLObjectType<*, *>,
selectionSet: SelectionSetNode,
fields: ObjMap<Array<FieldNode>>,
visitedFragmentNames: ObjMap<boolean>,
Expand Down Expand Up @@ -607,7 +607,7 @@ function shouldIncludeNode(
function doesFragmentConditionMatch(
exeContext: ExecutionContext,
fragment: FragmentDefinitionNode | InlineFragmentNode,
type: GraphQLObjectType,
type: GraphQLObjectType<*, *>,
): boolean {
const typeConditionNode = fragment.typeCondition;
if (!typeConditionNode) {
Expand Down Expand Up @@ -638,7 +638,7 @@ function getFieldEntryKey(node: FieldNode): string {
*/
function resolveField(
exeContext: ExecutionContext,
parentType: GraphQLObjectType,
parentType: GraphQLObjectType<*, *>,
source: mixed,
fieldNodes: $ReadOnlyArray<FieldNode>,
path: ResponsePath,
Expand Down Expand Up @@ -686,7 +686,7 @@ export function buildResolveInfo(
exeContext: ExecutionContext,
fieldDef: GraphQLField<*, *>,
fieldNodes: $ReadOnlyArray<FieldNode>,
parentType: GraphQLObjectType,
parentType: GraphQLObjectType<*, *>,
path: ResponsePath,
): GraphQLResolveInfo {
// The resolve function's optional fourth argument is a collection of
Expand Down Expand Up @@ -1030,13 +1030,13 @@ function completeAbstractValue(
}

function ensureValidRuntimeType(
runtimeTypeOrName: ?GraphQLObjectType | string,
runtimeTypeOrName: ?GraphQLObjectType<*, *> | string,
exeContext: ExecutionContext,
returnType: GraphQLAbstractType,
fieldNodes: $ReadOnlyArray<FieldNode>,
info: GraphQLResolveInfo,
result: mixed,
): GraphQLObjectType {
): GraphQLObjectType<*, *> {
const runtimeType =
typeof runtimeTypeOrName === 'string'
? exeContext.schema.getType(runtimeTypeOrName)
Expand Down Expand Up @@ -1069,7 +1069,7 @@ function ensureValidRuntimeType(
*/
function completeObjectValue(
exeContext: ExecutionContext,
returnType: GraphQLObjectType,
returnType: GraphQLObjectType<*, *>,
fieldNodes: $ReadOnlyArray<FieldNode>,
info: GraphQLResolveInfo,
path: ResponsePath,
Expand Down Expand Up @@ -1111,7 +1111,7 @@ function completeObjectValue(
}

function invalidReturnTypeError(
returnType: GraphQLObjectType,
returnType: GraphQLObjectType<*, *>,
result: mixed,
fieldNodes: $ReadOnlyArray<FieldNode>,
): GraphQLError {
Expand All @@ -1123,7 +1123,7 @@ function invalidReturnTypeError(

function collectAndExecuteSubfields(
exeContext: ExecutionContext,
returnType: GraphQLObjectType,
returnType: GraphQLObjectType<*, *>,
fieldNodes: $ReadOnlyArray<FieldNode>,
path: ResponsePath,
result: mixed,
Expand All @@ -1141,7 +1141,7 @@ function collectAndExecuteSubfields(
const collectSubfields = memoize3(_collectSubfields);
function _collectSubfields(
exeContext: ExecutionContext,
returnType: GraphQLObjectType,
returnType: GraphQLObjectType<*, *>,
fieldNodes: $ReadOnlyArray<FieldNode>,
): ObjMap<Array<FieldNode>> {
let subFieldNodes = Object.create(null);
Expand Down Expand Up @@ -1176,7 +1176,7 @@ function defaultResolveTypeFn(
contextValue: mixed,
info: GraphQLResolveInfo,
abstractType: GraphQLAbstractType,
): MaybePromise<?GraphQLObjectType | string> {
): MaybePromise<?GraphQLObjectType<*, *> | string> {
// First, look for `__typename`.
if (
value !== null &&
Expand Down Expand Up @@ -1248,7 +1248,7 @@ export const defaultFieldResolver: GraphQLFieldResolver<any, *> = function(
*/
export function getFieldDef(
schema: GraphQLSchema,
parentType: GraphQLObjectType,
parentType: GraphQLObjectType<*, *>,
fieldName: string,
): ?GraphQLField<*, *> {
if (
Expand Down
70 changes: 35 additions & 35 deletions src/type/definition.js
Expand Up @@ -46,8 +46,8 @@ import type { MaybePromise } from '../jsutils/MaybePromise';
* These are all of the possible kinds of types.
*/
export type GraphQLType =
| GraphQLScalarType
| GraphQLObjectType
| GraphQLScalarType<*, *>
| GraphQLObjectType<*, *>
| GraphQLInterfaceType
| GraphQLUnionType
| GraphQLEnumType
Expand Down Expand Up @@ -84,7 +84,7 @@ export function isScalarType(type) {
return instanceOf(type, GraphQLScalarType);
}

export function assertScalarType(type: mixed): GraphQLScalarType {
export function assertScalarType(type: mixed): GraphQLScalarType<*, *> {
invariant(
isScalarType(type),
`Expected ${inspect(type)} to be a GraphQL Scalar type.`,
Expand All @@ -99,7 +99,7 @@ export function isObjectType(type) {
return instanceOf(type, GraphQLObjectType);
}

export function assertObjectType(type: mixed): GraphQLObjectType {
export function assertObjectType(type: mixed): GraphQLObjectType<*, *> {
invariant(
isObjectType(type),
`Expected ${inspect(type)} to be a GraphQL Object type.`,
Expand Down Expand Up @@ -201,12 +201,12 @@ export function assertNonNullType(type: mixed): GraphQLNonNull<any> {
* These types may be used as input types for arguments and directives.
*/
export type GraphQLInputType =
| GraphQLScalarType
| GraphQLScalarType<*, *>
| GraphQLEnumType
| GraphQLInputObjectType
| GraphQLList<GraphQLInputType>
| GraphQLNonNull<
| GraphQLScalarType
| GraphQLScalarType<*, *>
| GraphQLEnumType
| GraphQLInputObjectType
| GraphQLList<GraphQLInputType>,
Expand All @@ -233,15 +233,15 @@ export function assertInputType(type: mixed): GraphQLInputType {
* These types may be used as output types as the result of fields.
*/
export type GraphQLOutputType =
| GraphQLScalarType
| GraphQLObjectType
| GraphQLScalarType<*, *>
| GraphQLObjectType<*, *>
| GraphQLInterfaceType
| GraphQLUnionType
| GraphQLEnumType
| GraphQLList<GraphQLOutputType>
| GraphQLNonNull<
| GraphQLScalarType
| GraphQLObjectType
| GraphQLScalarType<*, *>
| GraphQLObjectType<*, *>
| GraphQLInterfaceType
| GraphQLUnionType
| GraphQLEnumType
Expand Down Expand Up @@ -270,7 +270,7 @@ export function assertOutputType(type: mixed): GraphQLOutputType {
/**
* These types may describe types which may be leaf values.
*/
export type GraphQLLeafType = GraphQLScalarType | GraphQLEnumType;
export type GraphQLLeafType = GraphQLScalarType<*, *> | GraphQLEnumType;

export function isLeafType(type: mixed): boolean %checks {
return isScalarType(type) || isEnumType(type);
Expand All @@ -288,7 +288,7 @@ export function assertLeafType(type: mixed): GraphQLLeafType {
* These types may describe the parent context of a selection set.
*/
export type GraphQLCompositeType =
| GraphQLObjectType
| GraphQLObjectType<*, *>
| GraphQLInterfaceType
| GraphQLUnionType;

Expand Down Expand Up @@ -423,8 +423,8 @@ export function assertWrappingType(type: mixed): GraphQLWrappingType {
* These types can all accept null as a value.
*/
export type GraphQLNullableType =
| GraphQLScalarType
| GraphQLObjectType
| GraphQLScalarType<*, *>
| GraphQLObjectType<*, *>
| GraphQLInterfaceType
| GraphQLUnionType
| GraphQLEnumType
Expand Down Expand Up @@ -458,8 +458,8 @@ export function getNullableType(type) {
* These named types do not include modifiers like List or NonNull.
*/
export type GraphQLNamedType =
| GraphQLScalarType
| GraphQLObjectType
| GraphQLScalarType<any, any>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be <*, *>?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • is deprecated on flow type

| GraphQLObjectType<*, *>
| GraphQLInterfaceType
| GraphQLUnionType
| GraphQLEnumType
Expand Down Expand Up @@ -532,21 +532,21 @@ function resolveThunk<+T>(thunk: Thunk<T>): T {
* });
*
*/
export class GraphQLScalarType {
export class GraphQLScalarType<TInternal = any, TExternal = TInternal> {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you explain what the purpose of / difference between TInternal and TExternal is?

name: string;
description: ?string;
serialize: GraphQLScalarSerializer<*>;
parseValue: GraphQLScalarValueParser<*>;
parseLiteral: GraphQLScalarLiteralParser<*>;
serialize: GraphQLScalarSerializer<TExternal>;
parseValue: GraphQLScalarValueParser<TInternal>;
parseLiteral: GraphQLScalarLiteralParser<TInternal>;
astNode: ?ScalarTypeDefinitionNode;
extensionASTNodes: ?$ReadOnlyArray<ScalarTypeExtensionNode>;

constructor(config: GraphQLScalarTypeConfig<*, *>): void {
constructor(config: GraphQLScalarTypeConfig<TInternal, TExternal>): void {
this.name = config.name;
this.description = config.description;
this.serialize = config.serialize;
this.parseValue = config.parseValue || (value => value);
this.parseLiteral = config.parseLiteral || valueFromASTUntyped;
this.parseValue = config.parseValue || ((value): TInternal => (value: any));
this.parseLiteral = config.parseLiteral || (valueFromASTUntyped: GraphQLScalarLiteralParser<TInternal);
this.astNode = config.astNode;
this.extensionASTNodes = config.extensionASTNodes;
invariant(typeof config.name === 'string', 'Must provide name.');
Expand Down Expand Up @@ -632,17 +632,17 @@ export type GraphQLScalarTypeConfig<TInternal, TExternal> = {|
* });
*
*/
export class GraphQLObjectType {
export class GraphQLObjectType<TSource = any, TContext = any> {
name: string;
description: ?string;
astNode: ?ObjectTypeDefinitionNode;
extensionASTNodes: ?$ReadOnlyArray<ObjectTypeExtensionNode>;
isTypeOf: ?GraphQLIsTypeOfFn<*, *>;
isTypeOf: ?GraphQLIsTypeOfFn<TSource, TContext>;

_fields: Thunk<GraphQLFieldMap<*, *>>;
_fields: Thunk<GraphQLFieldMap<TSource, TContext>>;
_interfaces: Thunk<Array<GraphQLInterfaceType>>;

constructor(config: GraphQLObjectTypeConfig<*, *>): void {
constructor(config: GraphQLObjectTypeConfig<TSource, TContext>): void {
this.name = config.name;
this.description = config.description;
this.astNode = config.astNode;
Expand Down Expand Up @@ -681,8 +681,8 @@ export class GraphQLObjectType {
defineToStringTag(GraphQLObjectType);
defineToJSON(GraphQLObjectType);

function defineInterfaces(
config: GraphQLObjectTypeConfig<*, *>,
function defineInterfaces<TSource, TContext>(
config: GraphQLObjectTypeConfig<TSource, TContext>,
): Array<GraphQLInterfaceType> {
const interfaces = resolveThunk(config.interfaces) || [];
invariant(
Expand Down Expand Up @@ -770,7 +770,7 @@ export type GraphQLTypeResolver<TSource, TContext> = (
value: TSource,
context: TContext,
info: GraphQLResolveInfo,
) => MaybePromise<?GraphQLObjectType | string>;
) => MaybePromise<?GraphQLObjectType<TSource, TContext> | string>;

export type GraphQLIsTypeOfFn<TSource, TContext> = (
source: TSource,
Expand All @@ -793,7 +793,7 @@ export type GraphQLResolveInfo = {|
+fieldName: string,
+fieldNodes: $ReadOnlyArray<FieldNode>,
+returnType: GraphQLOutputType,
+parentType: GraphQLObjectType,
+parentType: GraphQLObjectType<*, *>,
+path: ResponsePath,
+schema: GraphQLSchema,
+fragments: ObjMap<FragmentDefinitionNode>,
Expand Down Expand Up @@ -968,7 +968,7 @@ export class GraphQLUnionType {
extensionASTNodes: ?$ReadOnlyArray<UnionTypeExtensionNode>;
resolveType: ?GraphQLTypeResolver<*, *>;

_types: Thunk<Array<GraphQLObjectType>>;
_types: Thunk<Array<GraphQLObjectType<*, *>>>;

constructor(config: GraphQLUnionTypeConfig<*, *>): void {
this.name = config.name;
Expand All @@ -985,7 +985,7 @@ export class GraphQLUnionType {
);
}

getTypes(): Array<GraphQLObjectType> {
getTypes(): Array<GraphQLObjectType<*, *>> {
if (typeof this._types === 'function') {
this._types = this._types();
}
Expand All @@ -1003,7 +1003,7 @@ defineToJSON(GraphQLUnionType);

function defineTypes(
config: GraphQLUnionTypeConfig<*, *>,
): Array<GraphQLObjectType> {
): Array<GraphQLObjectType<*, *>> {
const types = resolveThunk(config.types) || [];
invariant(
Array.isArray(types),
Expand All @@ -1015,7 +1015,7 @@ function defineTypes(

export type GraphQLUnionTypeConfig<TSource, TContext> = {|
name: string,
types: Thunk<Array<GraphQLObjectType>>,
types: Thunk<Array<GraphQLObjectType<*, *>>>,
/**
* Optionally provide a custom type resolver function. If one is not provided,
* the default implementation will call `isTypeOf` on each implementing
Expand Down
6 changes: 3 additions & 3 deletions src/type/scalars.js
Expand Up @@ -58,7 +58,7 @@ function coerceInt(value: mixed): number {
return value;
}

export const GraphQLInt = new GraphQLScalarType({
export const GraphQLInt = new GraphQLScalarType<number>({
name: 'Int',
description:
'The `Int` scalar type represents non-fractional signed whole numeric ' +
Expand Down Expand Up @@ -102,7 +102,7 @@ function coerceFloat(value: mixed): number {
return value;
}

export const GraphQLFloat = new GraphQLScalarType({
export const GraphQLFloat = new GraphQLScalarType<number>({
name: 'Float',
description:
'The `Float` scalar type represents signed double-precision fractional ' +
Expand Down Expand Up @@ -214,7 +214,7 @@ function coerceID(value: mixed): string {
throw new TypeError(`ID cannot represent value: ${inspect(value)}`);
}

export const GraphQLID = new GraphQLScalarType({
export const GraphQLID = new GraphQLScalarType<string | number>({
name: 'ID',
description:
'The `ID` scalar type represents a unique identifier, often used to ' +
Expand Down