diff --git a/.flowconfig b/.flowconfig index b40b9466f2..4c052127ea 100644 --- a/.flowconfig +++ b/.flowconfig @@ -10,7 +10,7 @@ [libs] [lints] -sketchy-null-bool=off +sketchy-null-bool=error sketchy-null-string=error sketchy-null-number=error sketchy-null-mixed=error @@ -35,6 +35,7 @@ uninitialized-instance-property=error include_warnings=true module.use_strict=true babel_loose_array_spread=true +esproposal.optional_chaining=enable suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(\\)?)\\) suppress_comment=\\(.\\|\n\\)*\\$DisableFlowOnNegativeTest diff --git a/src/error/GraphQLError.js b/src/error/GraphQLError.js index 5aa1a710a6..a37aeaeea8 100644 --- a/src/error/GraphQLError.js +++ b/src/error/GraphQLError.js @@ -99,8 +99,7 @@ export class GraphQLError extends Error { // Compute locations in the source for the given nodes/positions. let _source = source; if (!_source && _nodes) { - const node = _nodes[0]; - _source = node && node.loc && node.loc.source; + _source = _nodes[0].loc?.source; } let _positions = positions; @@ -188,7 +187,7 @@ export class GraphQLError extends Error { }); // Include (non-enumerable) stack trace. - if (originalError && originalError.stack) { + if (originalError?.stack) { Object.defineProperty(this, 'stack', { value: originalError.stack, writable: true, diff --git a/src/error/__tests__/GraphQLError-test.js b/src/error/__tests__/GraphQLError-test.js index 141fd61417..deba78b437 100644 --- a/src/error/__tests__/GraphQLError-test.js +++ b/src/error/__tests__/GraphQLError-test.js @@ -19,7 +19,7 @@ const source = new Source(dedent` `); const ast = parse(source); const operationNode = ast.definitions[0]; -invariant(operationNode && operationNode.kind === Kind.OPERATION_DEFINITION); +invariant(operationNode.kind === Kind.OPERATION_DEFINITION); const fieldNode = operationNode.selectionSet.selections[0]; invariant(fieldNode); @@ -161,7 +161,7 @@ describe('printError', () => { ), ); const opA = docA.definitions[0]; - invariant(opA && opA.kind === Kind.OBJECT_TYPE_DEFINITION && opA.fields); + invariant(opA.kind === Kind.OBJECT_TYPE_DEFINITION && opA.fields); const fieldA = opA.fields[0]; const docB = parse( @@ -175,7 +175,7 @@ describe('printError', () => { ), ); const opB = docB.definitions[0]; - invariant(opB && opB.kind === Kind.OBJECT_TYPE_DEFINITION && opB.fields); + invariant(opB.kind === Kind.OBJECT_TYPE_DEFINITION && opB.fields); const fieldB = opB.fields[0]; const error = new GraphQLError('Example error with two nodes', [ diff --git a/src/error/locatedError.js b/src/error/locatedError.js index 6e7b292202..bb273332fe 100644 --- a/src/error/locatedError.js +++ b/src/error/locatedError.js @@ -16,15 +16,15 @@ export function locatedError( ): GraphQLError { // Note: this uses a brand-check to support GraphQL errors originating from // other contexts. - if (originalError && Array.isArray(originalError.path)) { + if (Array.isArray(originalError.path)) { return (originalError: any); } return new GraphQLError( - originalError && originalError.message, - (originalError && (originalError: any).nodes) || nodes, - originalError && (originalError: any).source, - originalError && (originalError: any).positions, + originalError.message, + (originalError: any).nodes || nodes, + (originalError: any).source, + (originalError: any).positions, path, originalError, ); diff --git a/src/execution/__tests__/executor-test.js b/src/execution/__tests__/executor-test.js index 60bef79d46..a0e606beb8 100644 --- a/src/execution/__tests__/executor-test.js +++ b/src/execution/__tests__/executor-test.js @@ -292,7 +292,7 @@ describe('Execute: Handles basic execution tasks', () => { ); const operation = document.definitions[0]; - invariant(operation && operation.kind === Kind.OPERATION_DEFINITION); + invariant(operation.kind === Kind.OPERATION_DEFINITION); expect(resolvedInfo).to.include({ fieldName: 'test', @@ -1025,7 +1025,7 @@ describe('Execute: Handles basic execution tasks', () => { name: 'SpecialType', isTypeOf(obj, context) { const result = obj instanceof Special; - return context && context.async ? Promise.resolve(result) : result; + return context?.async ? Promise.resolve(result) : result; }, fields: { value: { type: GraphQLString } }, }); diff --git a/src/execution/execute.js b/src/execution/execute.js index 0c0cced6b9..adec10af28 100644 --- a/src/execution/execute.js +++ b/src/execution/execute.js @@ -296,7 +296,7 @@ export function buildExecutionContext( ]; } operation = definition; - } else if (definition.name && definition.name.value === operationName) { + } else if (definition.name?.value === operationName) { operation = definition; } break; @@ -554,7 +554,7 @@ function shouldIncludeNode( node, exeContext.variableValues, ); - if (skip && skip.if === true) { + if (skip?.if === true) { return false; } @@ -563,7 +563,7 @@ function shouldIncludeNode( node, exeContext.variableValues, ); - if (include && include.if === false) { + if (include?.if === false) { return false; } return true; diff --git a/src/execution/values.js b/src/execution/values.js index 3d5a28e8b4..bc1df4665d 100644 --- a/src/execution/values.js +++ b/src/execution/values.js @@ -50,7 +50,7 @@ export function getVariableValues( inputs: { +[variable: string]: mixed, ... }, options?: {| maxErrors?: number |}, ): CoercedVariableValues { - const maxErrors = options && options.maxErrors; + const maxErrors = options?.maxErrors; const errors = []; try { const coerced = coerceVariableValues(schema, varDefNodes, inputs, error => { diff --git a/src/jsutils/isPromise.js b/src/jsutils/isPromise.js index 53cc76644f..d6ef8177a0 100644 --- a/src/jsutils/isPromise.js +++ b/src/jsutils/isPromise.js @@ -9,5 +9,5 @@ declare function isPromise(value: mixed): boolean %checks(value instanceof // eslint-disable-next-line no-redeclare export default function isPromise(value) { - return value != null && typeof value.then === 'function'; + return typeof value?.then === 'function'; } diff --git a/src/language/__tests__/visitor-test.js b/src/language/__tests__/visitor-test.js index b920eac307..7781a94cab 100644 --- a/src/language/__tests__/visitor-test.js +++ b/src/language/__tests__/visitor-test.js @@ -500,7 +500,7 @@ describe('Visitor', () => { 'enter', node.kind, key, - parent && parent.kind != null ? parent.kind : undefined, + parent?.kind != null ? parent.kind : undefined, ]); checkVisitorFnArgs(ast, arguments); @@ -512,7 +512,7 @@ describe('Visitor', () => { 'leave', node.kind, key, - parent && parent.kind != null ? parent.kind : undefined, + parent?.kind != null ? parent.kind : undefined, ]); expect(argsStack.pop()).to.deep.equal([...arguments]); diff --git a/src/language/parser.js b/src/language/parser.js index 82e120ce2a..c76d6b7c40 100644 --- a/src/language/parser.js +++ b/src/language/parser.js @@ -164,7 +164,7 @@ export function parseType( } class Parser { - _options: ParseOptions; + _options: ?ParseOptions; _lexer: Lexer; constructor(source: string | Source, options?: ParseOptions) { @@ -175,12 +175,7 @@ class Parser { ); this._lexer = new Lexer(sourceObj); - this._options = options || { - noLocation: false, - allowLegacySDLEmptyFields: false, - allowLegacySDLImplementsInterfaces: false, - experimentalFragmentVariables: false, - }; + this._options = options; } /** @@ -483,7 +478,7 @@ class Parser { // Experimental support for defining variables within fragments changes // the grammar of FragmentDefinition: // - fragment FragmentName VariableDefinitions? on TypeCondition Directives? SelectionSet - if (this._options.experimentalFragmentVariables) { + if (this._options?.experimentalFragmentVariables === true) { return { kind: Kind.FRAGMENT_DEFINITION, name: this.parseFragmentName(), @@ -869,7 +864,7 @@ class Parser { } while ( this.expectOptionalToken(TokenKind.AMP) || // Legacy support for the SDL? - (this._options.allowLegacySDLImplementsInterfaces && + (this._options?.allowLegacySDLImplementsInterfaces === true && this.peek(TokenKind.NAME)) ); } @@ -882,7 +877,7 @@ class Parser { parseFieldsDefinition(): Array { // Legacy support for the SDL? if ( - this._options.allowLegacySDLEmptyFields && + this._options?.allowLegacySDLEmptyFields === true && this.peek(TokenKind.BRACE_L) && this._lexer.lookahead().kind === TokenKind.BRACE_R ) { @@ -1403,7 +1398,7 @@ class Parser { * the source that created a given parsed object. */ loc(startToken: Token): Location | void { - if (!this._options.noLocation) { + if (this._options?.noLocation !== true) { return new Location( startToken, this._lexer.lastToken, diff --git a/src/subscription/__tests__/mapAsyncIterator-test.js b/src/subscription/__tests__/mapAsyncIterator-test.js index d01f039fe1..ea5f012bde 100644 --- a/src/subscription/__tests__/mapAsyncIterator-test.js +++ b/src/subscription/__tests__/mapAsyncIterator-test.js @@ -273,7 +273,7 @@ describe('mapAsyncIterator', () => { } catch (e) { caughtError = e; } - expect(caughtError && caughtError.message).to.equal('Goodbye'); + expect(caughtError?.message).to.equal('Goodbye'); }); it('maps over thrown errors if second callback provided', async () => { @@ -295,7 +295,7 @@ describe('mapAsyncIterator', () => { const result = await doubles.next(); expect(result.value).to.be.instanceof(Error); - expect(result.value && result.value.message).to.equal('Goodbye'); + expect(result.value?.message).to.equal('Goodbye'); expect(result.done).to.equal(false); expect(await doubles.next()).to.deep.equal({ diff --git a/src/subscription/__tests__/subscribe-test.js b/src/subscription/__tests__/subscribe-test.js index a40c48d422..eb4fb76536 100644 --- a/src/subscription/__tests__/subscribe-test.js +++ b/src/subscription/__tests__/subscribe-test.js @@ -142,7 +142,7 @@ async function expectPromiseToThrow(promise, message) { /* istanbul ignore next */ expect.fail('promise should have thrown but did not'); } catch (error) { - expect(error && error.message).to.equal(message); + expect(error?.message).to.equal(message); } } diff --git a/src/type/directives.js b/src/type/directives.js index 47f33a9d0b..6098a4167a 100644 --- a/src/type/directives.js +++ b/src/type/directives.js @@ -65,7 +65,7 @@ export class GraphQLDirective { this.name = config.name; this.description = config.description; this.locations = config.locations; - this.isRepeatable = config.isRepeatable != null && config.isRepeatable; + this.isRepeatable = config.isRepeatable || false; this.extensions = config.extensions && toObjMap(config.extensions); this.astNode = config.astNode; diff --git a/src/type/schema.js b/src/type/schema.js index 1d8909726f..4a0a345615 100644 --- a/src/type/schema.js +++ b/src/type/schema.js @@ -138,7 +138,7 @@ export class GraphQLSchema { constructor(config: $ReadOnly): void { // If this schema was built from a source known to be valid, then it may be // marked with assumeValid to avoid an additional type system validation. - if (config && config.assumeValid) { + if (config.assumeValid === true) { this.__validationErrors = []; } else { this.__validationErrors = undefined; diff --git a/src/type/validate.js b/src/type/validate.js index 4b03fc09b1..2c13e51865 100644 --- a/src/type/validate.js +++ b/src/type/validate.js @@ -156,7 +156,7 @@ function validateDirectives(context: SchemaValidationContext): void { if (!isDirective(directive)) { context.reportError( `Expected directive but got: ${inspect(directive)}.`, - directive && directive.astNode, + directive?.astNode, ); continue; } @@ -204,7 +204,7 @@ function validateTypes(context: SchemaValidationContext): void { if (!isNamedType(type)) { context.reportError( `Expected GraphQL named type but got: ${inspect(type)}.`, - type && type.astNode, + type?.astNode, ); continue; } @@ -265,7 +265,7 @@ function validateFields( context.reportError( `The type of ${type.name}.${field.name} must be Output Type ` + `but got: ${inspect(field.type)}.`, - field.astNode && field.astNode.type, + field.astNode?.type, ); } @@ -281,7 +281,7 @@ function validateFields( context.reportError( `The type of ${type.name}.${field.name}(${argName}:) must be Input ` + `Type but got: ${inspect(arg.type)}.`, - arg.astNode && arg.astNode.type, + arg.astNode?.type, ); } } @@ -354,10 +354,7 @@ function validateTypeImplementsInterface( `Interface field ${iface.name}.${fieldName} expects type ` + `${inspect(ifaceField.type)} but ${type.name}.${fieldName} ` + `is type ${inspect(typeField.type)}.`, - [ - ifaceField.astNode && ifaceField.astNode.type, - typeField.astNode && typeField.astNode.type, - ], + [ifaceField.astNode?.type, typeField.astNode?.type], ); } @@ -384,10 +381,7 @@ function validateTypeImplementsInterface( `expects type ${inspect(ifaceArg.type)} but ` + `${type.name}.${fieldName}(${argName}:) is type ` + `${inspect(typeArg.type)}.`, - [ - ifaceArg.astNode && ifaceArg.astNode.type, - typeArg.astNode && typeArg.astNode.type, - ], + [ifaceArg.astNode?.type, typeArg.astNode?.type], ); } @@ -512,7 +506,7 @@ function validateInputFields( context.reportError( `The type of ${inputObj.name}.${field.name} must be Input Type ` + `but got: ${inspect(field.type)}.`, - field.astNode && field.astNode.type, + field.astNode?.type, ); } } diff --git a/src/utilities/__tests__/buildASTSchema-test.js b/src/utilities/__tests__/buildASTSchema-test.js index 47fe0bab8c..e4ea5a80b6 100644 --- a/src/utilities/__tests__/buildASTSchema-test.js +++ b/src/utilities/__tests__/buildASTSchema-test.js @@ -51,7 +51,7 @@ function cycleSDL(sdl, options = {}) { } function printASTNode(obj) { - invariant(obj != null && obj.astNode != null); + invariant(obj?.astNode != null); return print(obj.astNode); } diff --git a/src/utilities/__tests__/extendSchema-test.js b/src/utilities/__tests__/extendSchema-test.js index a9571130a5..cb329abaff 100644 --- a/src/utilities/__tests__/extendSchema-test.js +++ b/src/utilities/__tests__/extendSchema-test.js @@ -37,7 +37,7 @@ import { extendSchema } from '../extendSchema'; import { buildSchema } from '../buildASTSchema'; function printExtensionNodes(obj) { - invariant(obj && obj.extensionASTNodes); + invariant(obj?.extensionASTNodes != null); return print({ kind: Kind.DOCUMENT, definitions: obj.extensionASTNodes, @@ -56,7 +56,7 @@ function printSchemaChanges(schema, extendedSchema) { } function printASTNode(obj) { - invariant(obj != null && obj.astNode != null); + invariant(obj?.astNode != null); return print(obj.astNode); } diff --git a/src/utilities/astFromValue.js b/src/utilities/astFromValue.js index bcee6461c3..067bdc6b7a 100644 --- a/src/utilities/astFromValue.js +++ b/src/utilities/astFromValue.js @@ -47,7 +47,7 @@ import { export function astFromValue(value: mixed, type: GraphQLInputType): ?ValueNode { if (isNonNullType(type)) { const astValue = astFromValue(value, type.ofType); - if (astValue && astValue.kind === Kind.NULL) { + if (astValue?.kind === Kind.NULL) { return null; } return astValue; diff --git a/src/utilities/buildASTSchema.js b/src/utilities/buildASTSchema.js index 0259e2c1d2..5e5dbed2bb 100644 --- a/src/utilities/buildASTSchema.js +++ b/src/utilities/buildASTSchema.js @@ -63,11 +63,11 @@ export function buildASTSchema( options?: BuildSchemaOptions, ): GraphQLSchema { devAssert( - documentAST && documentAST.kind === Kind.DOCUMENT, + documentAST != null && documentAST.kind === Kind.DOCUMENT, 'Must provide valid Document AST.', ); - if (!options || !(options.assumeValid || options.assumeValidSDL)) { + if (options?.assumeValid !== true && options?.assumeValidSDL !== true) { assertValidSDL(documentAST); } @@ -123,18 +123,17 @@ export function buildSchema( options?: {| ...BuildSchemaOptions, ...ParseOptions |}, ): GraphQLSchema { const document = parse(source, { - noLocation: (options && options.noLocation) || false, - allowLegacySDLEmptyFields: - (options && options.allowLegacySDLEmptyFields) || false, + noLocation: options?.noLocation || false, + allowLegacySDLEmptyFields: options?.allowLegacySDLEmptyFields || false, allowLegacySDLImplementsInterfaces: - (options && options.allowLegacySDLImplementsInterfaces) || false, + options?.allowLegacySDLImplementsInterfaces || false, experimentalFragmentVariables: - (options && options.experimentalFragmentVariables) || false, + options?.experimentalFragmentVariables || false, }); return buildASTSchema(document, { - commentDescriptions: (options && options.commentDescriptions) || false, - assumeValidSDL: (options && options.assumeValidSDL) || false, - assumeValid: (options && options.assumeValid) || false, + commentDescriptions: options?.commentDescriptions || false, + assumeValidSDL: options?.assumeValidSDL || false, + assumeValid: options?.assumeValid || false, }); } diff --git a/src/utilities/buildClientSchema.js b/src/utilities/buildClientSchema.js index 7d9e1e8959..8c8566f57f 100644 --- a/src/utilities/buildClientSchema.js +++ b/src/utilities/buildClientSchema.js @@ -122,7 +122,7 @@ export function buildClientSchema( subscription: subscriptionType, types: objectValues(typeMap), directives, - assumeValid: options && options.assumeValid, + assumeValid: options?.assumeValid, }); // Given a type reference in introspection, return the GraphQLType instance. @@ -201,7 +201,7 @@ export function buildClientSchema( // Given a type's introspection result, construct the correct // GraphQLType instance. function buildType(type: IntrospectionType): GraphQLNamedType { - if (type && type.name && type.kind) { + if (type != null && type.name != null && type.kind != null) { switch (type.kind) { case TypeKind.SCALAR: return buildScalarDef(type); diff --git a/src/utilities/extendSchema.js b/src/utilities/extendSchema.js index c4b6d700f9..618af75cb4 100644 --- a/src/utilities/extendSchema.js +++ b/src/utilities/extendSchema.js @@ -131,11 +131,11 @@ export function extendSchema( assertSchema(schema); devAssert( - documentAST && documentAST.kind === Kind.DOCUMENT, + documentAST != null && documentAST.kind === Kind.DOCUMENT, 'Must provide valid Document AST.', ); - if (!options || !(options.assumeValid || options.assumeValidSDL)) { + if (options?.assumeValid !== true && options?.assumeValidSDL !== true) { assertValidSDLExtension(documentAST, schema); } @@ -191,7 +191,7 @@ export function extendSchemaImpl( typeDefs.length === 0 && directiveDefs.length === 0 && schemaExtensions.length === 0 && - !schemaDef + schemaDef == null ) { return schemaConfig; } @@ -231,7 +231,7 @@ export function extendSchemaImpl( schemaConfig.extensionASTNodes, schemaExtensions, ), - assumeValid: (options && options.assumeValid) || false, + assumeValid: options?.assumeValid || false, }; // Below are functions used for producing this schema that have closed over @@ -729,7 +729,7 @@ function getDeprecationReason( node: EnumValueDefinitionNode | FieldDefinitionNode, ): ?string { const deprecated = getDirectiveValues(GraphQLDeprecatedDirective, node); - return deprecated && (deprecated.reason: any); + return (deprecated?.reason: any); } /** @@ -749,7 +749,7 @@ export function getDescription( if (node.description) { return node.description.value; } - if (options && options.commentDescriptions) { + if (options?.commentDescriptions === true) { const rawValue = getLeadingCommentBlock(node); if (rawValue !== undefined) { return dedentBlockStringValue('\n' + rawValue); @@ -765,7 +765,7 @@ function getLeadingCommentBlock(node): void | string { const comments = []; let token = loc.startToken.prev; while ( - token && + token != null && token.kind === TokenKind.COMMENT && token.next && token.prev && diff --git a/src/utilities/findDeprecatedUsages.js b/src/utilities/findDeprecatedUsages.js index 534b4ff0bf..e63003b7e5 100644 --- a/src/utilities/findDeprecatedUsages.js +++ b/src/utilities/findDeprecatedUsages.js @@ -28,7 +28,7 @@ export function findDeprecatedUsages( Field(node) { const parentType = typeInfo.getParentType(); const fieldDef = typeInfo.getFieldDef(); - if (parentType && fieldDef && fieldDef.deprecationReason != null) { + if (parentType && fieldDef?.deprecationReason != null) { errors.push( new GraphQLError( `The field "${parentType.name}.${fieldDef.name}" is deprecated. ` + @@ -41,7 +41,7 @@ export function findDeprecatedUsages( EnumValue(node) { const type = getNamedType(typeInfo.getInputType()); const enumVal = typeInfo.getEnumValue(); - if (type && enumVal && enumVal.deprecationReason != null) { + if (type && enumVal?.deprecationReason != null) { errors.push( new GraphQLError( `The enum value "${type.name}.${enumVal.name}" is deprecated. ` + diff --git a/src/utilities/getIntrospectionQuery.js b/src/utilities/getIntrospectionQuery.js index ceb22a8dcf..11ddede61a 100644 --- a/src/utilities/getIntrospectionQuery.js +++ b/src/utilities/getIntrospectionQuery.js @@ -9,7 +9,7 @@ export type IntrospectionOptions = {| |}; export function getIntrospectionQuery(options?: IntrospectionOptions): string { - const descriptions = !(options && options.descriptions === false); + const descriptions = options?.descriptions !== false ? 'description' : ''; return ` query IntrospectionQuery { __schema { @@ -21,7 +21,7 @@ export function getIntrospectionQuery(options?: IntrospectionOptions): string { } directives { name - ${descriptions ? 'description' : ''} + ${descriptions} locations args { ...InputValue @@ -33,10 +33,10 @@ export function getIntrospectionQuery(options?: IntrospectionOptions): string { fragment FullType on __Type { kind name - ${descriptions ? 'description' : ''} + ${descriptions} fields(includeDeprecated: true) { name - ${descriptions ? 'description' : ''} + ${descriptions} args { ...InputValue } @@ -54,7 +54,7 @@ export function getIntrospectionQuery(options?: IntrospectionOptions): string { } enumValues(includeDeprecated: true) { name - ${descriptions ? 'description' : ''} + ${descriptions} isDeprecated deprecationReason } @@ -65,7 +65,7 @@ export function getIntrospectionQuery(options?: IntrospectionOptions): string { fragment InputValue on __InputValue { name - ${descriptions ? 'description' : ''} + ${descriptions} type { ...TypeRef } defaultValue } diff --git a/src/utilities/getOperationAST.js b/src/utilities/getOperationAST.js index 6b34b6dcea..7e3dbcbe16 100644 --- a/src/utilities/getOperationAST.js +++ b/src/utilities/getOperationAST.js @@ -26,7 +26,7 @@ export function getOperationAST( return null; } operation = definition; - } else if (definition.name && definition.name.value === operationName) { + } else if (definition.name?.value === operationName) { return definition; } } diff --git a/src/utilities/schemaPrinter.js b/src/utilities/schemaPrinter.js index aa5f2435db..4edcc19dbb 100644 --- a/src/utilities/schemaPrinter.js +++ b/src/utilities/schemaPrinter.js @@ -333,7 +333,7 @@ function printDescription( return ''; } - if (options && options.commentDescriptions) { + if (options?.commentDescriptions === true) { return printDescriptionWithComments(description, indentation, firstInBlock); } diff --git a/src/validation/rules/LoneSchemaDefinition.js b/src/validation/rules/LoneSchemaDefinition.js index b44953e570..a07948e8e5 100644 --- a/src/validation/rules/LoneSchemaDefinition.js +++ b/src/validation/rules/LoneSchemaDefinition.js @@ -15,11 +15,10 @@ export function LoneSchemaDefinition( ): ASTVisitor { const oldSchema = context.getSchema(); const alreadyDefined = - oldSchema && - (oldSchema.astNode || - oldSchema.getQueryType() || - oldSchema.getMutationType() || - oldSchema.getSubscriptionType()); + oldSchema?.astNode || + oldSchema?.getQueryType() || + oldSchema?.getMutationType() || + oldSchema?.getSubscriptionType(); let schemaDefinitionsCount = 0; return { diff --git a/src/validation/rules/OverlappingFieldsCanBeMerged.js b/src/validation/rules/OverlappingFieldsCanBeMerged.js index 5406161763..14ea4feda8 100644 --- a/src/validation/rules/OverlappingFieldsCanBeMerged.js +++ b/src/validation/rules/OverlappingFieldsCanBeMerged.js @@ -559,10 +559,6 @@ function findConflict( isObjectType(parentType1) && isObjectType(parentType2)); - // The return type for each field. - const type1 = def1 && def1.type; - const type2 = def2 && def2.type; - if (!areMutuallyExclusive) { // Two aliases must refer to the same field. const name1 = node1.name.value; @@ -589,6 +585,10 @@ function findConflict( } } + // The return type for each field. + const type1 = def1?.type; + const type2 = def2?.type; + if (type1 && type2 && doTypesConflict(type1, type2)) { return [ [ diff --git a/src/validation/rules/PossibleTypeExtensions.js b/src/validation/rules/PossibleTypeExtensions.js index a4ba78776d..a1dc2aba32 100644 --- a/src/validation/rules/PossibleTypeExtensions.js +++ b/src/validation/rules/PossibleTypeExtensions.js @@ -51,7 +51,7 @@ export function PossibleTypeExtensions( function checkExtension(node) { const typeName = node.name.value; const defNode = definedTypes[typeName]; - const existingType = schema && schema.getType(typeName); + const existingType = schema?.getType(typeName); let expectedKind; if (defNode) { diff --git a/src/validation/rules/UniqueDirectiveNames.js b/src/validation/rules/UniqueDirectiveNames.js index e555d7a590..a8f6cb95c3 100644 --- a/src/validation/rules/UniqueDirectiveNames.js +++ b/src/validation/rules/UniqueDirectiveNames.js @@ -20,7 +20,7 @@ export function UniqueDirectiveNames( DirectiveDefinition(node) { const directiveName = node.name.value; - if (schema && schema.getDirective(directiveName)) { + if (schema?.getDirective(directiveName)) { context.reportError( new GraphQLError( `Directive "@${directiveName}" already exists in the schema. It cannot be redefined.`, diff --git a/src/validation/rules/UniqueTypeNames.js b/src/validation/rules/UniqueTypeNames.js index 58ba64a946..a5d8c824ef 100644 --- a/src/validation/rules/UniqueTypeNames.js +++ b/src/validation/rules/UniqueTypeNames.js @@ -28,7 +28,7 @@ export function UniqueTypeNames(context: SDLValidationContext): ASTVisitor { function checkTypeName(node: TypeDefinitionNode) { const typeName = node.name.value; - if (schema && schema.getType(typeName)) { + if (schema?.getType(typeName)) { context.reportError( new GraphQLError( `Type "${typeName}" already exists in the schema. It cannot also be defined in this type definition.`, diff --git a/src/validation/validate.js b/src/validation/validate.js index 6adc314d1c..63361e990b 100644 --- a/src/validation/validate.js +++ b/src/validation/validate.js @@ -49,13 +49,12 @@ export function validate( const abortObj = Object.freeze({}); const errors = []; - const maxErrors = options && options.maxErrors; const context = new ValidationContext( schema, documentAST, typeInfo, error => { - if (maxErrors != null && errors.length >= maxErrors) { + if (options.maxErrors != null && errors.length >= options.maxErrors) { errors.push( new GraphQLError( 'Too many validation errors, error limit reached. Validation aborted.',