From 86523ec5f80b459d43b6b16db80b185f903f49e5 Mon Sep 17 00:00:00 2001 From: Ivan Goncharov Date: Wed, 12 May 2021 14:11:43 +0300 Subject: [PATCH] Flow: Replace force type conversion with explicit $FlowFixMe comments (#3081) In preparation for TS convertion --- src/error/GraphQLError.js | 3 +- src/error/__tests__/locatedError-test.js | 22 +++-- src/error/locatedError.js | 12 ++- src/execution/__tests__/abstract-test.js | 8 +- src/execution/__tests__/executor-test.js | 3 +- src/jsutils/__tests__/inspect-test.js | 3 +- src/language/__tests__/predicates-test.js | 11 ++- src/language/lexer.js | 4 +- src/language/parser.js | 24 +++-- .../__tests__/buildClientSchema-test.js | 89 ++++++++++++------- .../__tests__/coerceInputValue-test.js | 39 ++++---- src/utilities/buildASTSchema.js | 9 +- src/utilities/extendSchema.js | 71 ++++++--------- src/utilities/findBreakingChanges.js | 8 +- src/utilities/introspectionFromSchema.js | 4 +- src/utilities/lexicographicSortSchema.js | 3 +- 16 files changed, 178 insertions(+), 135 deletions(-) diff --git a/src/error/GraphQLError.js b/src/error/GraphQLError.js index a8cb027bd4..6ea6a54206 100644 --- a/src/error/GraphQLError.js +++ b/src/error/GraphQLError.js @@ -133,7 +133,8 @@ export class GraphQLError extends Error { } } - Object.defineProperties((this: any), { + // $FlowFixMe[cannot-write] FIXME + Object.defineProperties(this, { name: { value: 'GraphQLError' }, message: { value: message, diff --git a/src/error/__tests__/locatedError-test.js b/src/error/__tests__/locatedError-test.js index 3de473b4c9..37d829998b 100644 --- a/src/error/__tests__/locatedError-test.js +++ b/src/error/__tests__/locatedError-test.js @@ -17,20 +17,26 @@ describe('locatedError', () => { }); it('passes GraphQLError-ish through', () => { - const e = new Error('I have a different prototype chain'); - (e: any).locations = []; - (e: any).path = []; - (e: any).nodes = []; - (e: any).source = null; - (e: any).positions = []; - (e: any).name = 'GraphQLError'; + const e = new Error(); + // $FlowExpectedError[prop-missing] + e.locations = []; + // $FlowExpectedError[prop-missing] + e.path = []; + // $FlowExpectedError[prop-missing] + e.nodes = []; + // $FlowExpectedError[prop-missing] + e.source = null; + // $FlowExpectedError[prop-missing] + e.positions = []; + e.name = 'GraphQLError'; expect(locatedError(e, [], [])).to.deep.equal(e); }); it('does not pass through elasticsearch-like errors', () => { const e = new Error('I am from elasticsearch'); - (e: any).path = '/something/feed/_search'; + // $FlowExpectedError[prop-missing] + e.path = '/something/feed/_search'; expect(locatedError(e, [], [])).to.not.deep.equal(e); }); diff --git a/src/error/locatedError.js b/src/error/locatedError.js index 34fd247855..31799defcd 100644 --- a/src/error/locatedError.js +++ b/src/error/locatedError.js @@ -22,14 +22,18 @@ export function locatedError( // Note: this uses a brand-check to support GraphQL errors originating from other contexts. if (Array.isArray(originalError.path)) { - return (originalError: any); + // $FlowExpectedError[incompatible-return] + return originalError; } return new GraphQLError( originalError.message, - (originalError: any).nodes ?? nodes, - (originalError: any).source, - (originalError: any).positions, + // $FlowFixMe[prop-missing] FIXME + originalError.nodes ?? nodes, + // $FlowFixMe[prop-missing] FIXME + originalError.source, + // $FlowFixMe[prop-missing] FIXME + originalError.positions, path, originalError, ); diff --git a/src/execution/__tests__/abstract-test.js b/src/execution/__tests__/abstract-test.js index b39167ddce..9409204edc 100644 --- a/src/execution/__tests__/abstract-test.js +++ b/src/execution/__tests__/abstract-test.js @@ -6,6 +6,7 @@ import { parse } from '../../language/parser'; import { GraphQLSchema } from '../../type/schema'; import { GraphQLString, GraphQLBoolean } from '../../type/scalars'; import { + assertInterfaceType, GraphQLList, GraphQLObjectType, GraphQLInterfaceType, @@ -569,13 +570,16 @@ describe('Execute: Handles execution of abstract types', () => { ); // FIXME: workaround since we can't inject resolveType into SDL - (schema.getType('Pet'): any).resolveType = () => []; + // $FlowExpectedError[incompatible-type] + assertInterfaceType(schema.getType('Pet')).resolveType = () => []; expectError({ forTypeName: undefined }).toEqual( 'Abstract type "Pet" must resolve to an Object type at runtime for field "Query.pet" with value { __typename: undefined }, received "[]".', ); // FIXME: workaround since we can't inject resolveType into SDL - (schema.getType('Pet'): any).resolveType = () => schema.getType('Cat'); + assertInterfaceType(schema.getType('Pet')).resolveType = + // $FlowExpectedError[incompatible-type] + () => schema.getType('Cat'); expectError({ forTypeName: undefined }).toEqual( 'Support for returning GraphQLObjectType from resolveType was removed in graphql-js@16.0.0 please return type name instead.', ); diff --git a/src/execution/__tests__/executor-test.js b/src/execution/__tests__/executor-test.js index 32464aed92..689151c587 100644 --- a/src/execution/__tests__/executor-test.js +++ b/src/execution/__tests__/executor-test.js @@ -489,7 +489,8 @@ describe('Execute: Handles basic execution tasks', () => { }, asyncReturnErrorWithExtensions() { const error = new Error('Error getting asyncReturnErrorWithExtensions'); - (error: any).extensions = { foo: 'bar' }; + // $FlowExpectedError[prop-missing] + error.extensions = { foo: 'bar' }; return Promise.resolve(error); }, diff --git a/src/jsutils/__tests__/inspect-test.js b/src/jsutils/__tests__/inspect-test.js index 7c3197e581..3db57fbe92 100644 --- a/src/jsutils/__tests__/inspect-test.js +++ b/src/jsutils/__tests__/inspect-test.js @@ -165,7 +165,8 @@ describe('inspect', () => { expect(inspect([[new Foo()]])).to.equal('[[[Foo]]]'); - (Foo.prototype: any)[Symbol.toStringTag] = 'Bar'; + // $FlowExpectedError[prop-missing] + Foo.prototype[Symbol.toStringTag] = 'Bar'; expect(inspect([[new Foo()]])).to.equal('[[[Bar]]]'); // eslint-disable-next-line func-names diff --git a/src/language/__tests__/predicates-test.js b/src/language/__tests__/predicates-test.js index 308551bf81..83afcdad72 100644 --- a/src/language/__tests__/predicates-test.js +++ b/src/language/__tests__/predicates-test.js @@ -17,12 +17,11 @@ import { isTypeExtensionNode, } from '../predicates'; -const allASTNodes: Array = Object.values(Kind).map( - (kind) => ({ kind }: any), -); - -function filterNodes(predicate: (node: ASTNode) => boolean): Array { - return allASTNodes.filter(predicate).map(({ kind }) => kind); +function filterNodes(predicate: (ASTNode) => boolean): Array { + return Object.values(Kind).filter( + // $FlowExpectedError[speculation-ambiguous] create node only with kind + (kind) => predicate({ kind }), + ); } describe('AST node predicates', () => { diff --git a/src/language/lexer.js b/src/language/lexer.js index ad42ce9897..3622e73468 100644 --- a/src/language/lexer.js +++ b/src/language/lexer.js @@ -64,8 +64,8 @@ export class Lexer { let token = this.token; if (token.kind !== TokenKind.EOF) { do { - // Note: next is only mutable during parsing, so we cast to allow this. - token = token.next ?? ((token: any).next = readToken(this, token)); + // $FlowFixMe[cannot-write] next is only mutable during parsing, so we cast to allow this. + token = token.next ?? (token.next = readToken(this, token)); } while (token.kind === TokenKind.COMMENT); } return token; diff --git a/src/language/parser.js b/src/language/parser.js index a366ac6895..a2b5a0b0b7 100644 --- a/src/language/parser.js +++ b/src/language/parser.js @@ -184,7 +184,8 @@ export class Parser { const token = this.expectToken(TokenKind.NAME); return this.node(token, { kind: Kind.NAME, - value: ((token.value: any): string), + // $FlowFixMe[incompatible-return] FIXME + value: token.value, }); } @@ -413,7 +414,8 @@ export class Parser { } parseConstArgument(): ConstArgumentNode { - return (this.parseArgument(true): any); + // $FlowFixMe[incompatible-return] FIXME during TS conversion + return this.parseArgument(true); } // Implements the parsing rules in the Fragments section. @@ -517,13 +519,15 @@ export class Parser { this._lexer.advance(); return this.node(token, { kind: Kind.INT, - value: ((token.value: any): string), + // $FlowFixMe[incompatible-return] FIXME + value: token.value, }); case TokenKind.FLOAT: this._lexer.advance(); return this.node(token, { kind: Kind.FLOAT, - value: ((token.value: any): string), + // $FlowFixMe[incompatible-return] FIXME + value: token.value, }); case TokenKind.STRING: case TokenKind.BLOCK_STRING: @@ -540,7 +544,8 @@ export class Parser { default: return this.node(token, { kind: Kind.ENUM, - value: ((token.value: any): string), + // $FlowFixMe[incompatible-return] FIXME + value: token.value, }); } case TokenKind.DOLLAR: @@ -563,7 +568,8 @@ export class Parser { } parseConstValueLiteral(): ConstValueNode { - return (this.parseValueLiteral(true): any); + // $FlowFixMe[incompatible-return] FIXME during TS conversion + return this.parseValueLiteral(true); } parseStringLiteral(): StringValueNode { @@ -571,7 +577,8 @@ export class Parser { this._lexer.advance(); return this.node(token, { kind: Kind.STRING, - value: ((token.value: any): string), + // $FlowFixMe[incompatible-return] FIXME + value: token.value, block: token.kind === TokenKind.BLOCK_STRING, }); } @@ -631,7 +638,8 @@ export class Parser { } parseConstDirectives(): Array { - return (this.parseDirectives(true): any); + // $FlowFixMe[incompatible-return] FIXME during TS conversion + return this.parseDirectives(true); } /** diff --git a/src/utilities/__tests__/buildClientSchema-test.js b/src/utilities/__tests__/buildClientSchema-test.js index bc03e3245b..d3d0be8899 100644 --- a/src/utilities/__tests__/buildClientSchema-test.js +++ b/src/utilities/__tests__/buildClientSchema-test.js @@ -3,6 +3,8 @@ import { describe, it } from 'mocha'; import { dedent } from '../../__testUtils__/dedent'; +import { invariant } from '../../jsutils/invariant'; + import { graphqlSync } from '../../graphql'; import { GraphQLSchema } from '../../type/schema'; @@ -72,7 +74,8 @@ describe('Type System: build schema from introspection', () => { const schema = buildSchema(sdl); const introspection = introspectionFromSchema(schema); - delete (introspection: any).__schema.queryType; + // $FlowExpectedError[cannot-write] + delete introspection.__schema.queryType; const clientSchema = buildClientSchema(introspection); expect(clientSchema.getQueryType()).to.equal(null); @@ -472,7 +475,8 @@ describe('Type System: build schema from introspection', () => { const schema = buildSchema(sdl); const introspection = introspectionFromSchema(schema); - delete (introspection: any).__schema.directives; + // $FlowExpectedError[cannot-write] + delete introspection.__schema.directives; const clientSchema = buildClientSchema(introspection); @@ -639,7 +643,8 @@ describe('Type System: build schema from introspection', () => { it('throws when referenced unknown type', () => { const introspection = introspectionFromSchema(dummySchema); - (introspection: any).__schema.types = introspection.__schema.types.filter( + // $FlowExpectedError[cannot-write] + introspection.__schema.types = introspection.__schema.types.filter( ({ name }) => name !== 'Query', ); @@ -656,7 +661,8 @@ describe('Type System: build schema from introspection', () => { `); const introspection = introspectionFromSchema(schema); - (introspection: any).__schema.types = introspection.__schema.types.filter( + // $FlowExpectedError[cannot-write] + introspection.__schema.types = introspection.__schema.types.filter( ({ name }) => name !== 'Float', ); @@ -670,7 +676,8 @@ describe('Type System: build schema from introspection', () => { expect(introspection).to.have.nested.property('__schema.queryType.name'); - delete (introspection: any).__schema.queryType.name; + // $FlowExpectedError[cannot-write] + delete introspection.__schema.queryType.name; expect(() => buildClientSchema(introspection)).to.throw( 'Unknown type reference: {}.', @@ -683,9 +690,9 @@ describe('Type System: build schema from introspection', () => { ({ name }) => name === 'Query', ); - expect(queryTypeIntrospection).to.have.property('kind'); - - delete (queryTypeIntrospection: any).kind; + invariant(queryTypeIntrospection?.kind === 'OBJECT'); + // $FlowExpectedError[cannot-write] + delete queryTypeIntrospection.kind; expect(() => buildClientSchema(introspection)).to.throw( /Invalid or incomplete introspection result. Ensure that a full introspection query is used in order to build a client schema: { name: "Query", .* }\./, @@ -700,7 +707,9 @@ describe('Type System: build schema from introspection', () => { expect(queryTypeIntrospection).to.have.property('interfaces'); - delete (queryTypeIntrospection: any).interfaces; + invariant(queryTypeIntrospection?.kind === 'OBJECT'); + // $FlowExpectedError[cannot-write] + delete queryTypeIntrospection.interfaces; expect(() => buildClientSchema(introspection)).to.throw( /Introspection result missing interfaces: { kind: "OBJECT", name: "Query", .* }\./, @@ -713,8 +722,9 @@ describe('Type System: build schema from introspection', () => { ({ name }) => name === 'SomeInterface', ); - expect(someInterfaceIntrospection).to.have.property('interfaces'); - (someInterfaceIntrospection: any).interfaces = null; + invariant(someInterfaceIntrospection?.kind === 'INTERFACE'); + // $FlowExpectedError[cannot-write] + someInterfaceIntrospection.interfaces = null; const clientSchema = buildClientSchema(introspection); expect(printSchema(clientSchema)).to.equal(printSchema(dummySchema)); @@ -726,8 +736,9 @@ describe('Type System: build schema from introspection', () => { ({ name }) => name === 'Query', ); - expect(queryTypeIntrospection).to.have.property('fields'); - delete (queryTypeIntrospection: any).fields; + invariant(queryTypeIntrospection?.kind === 'OBJECT'); + // $FlowExpectedError[cannot-write] + delete queryTypeIntrospection.fields; expect(() => buildClientSchema(introspection)).to.throw( /Introspection result missing fields: { kind: "OBJECT", name: "Query", .* }\./, @@ -740,8 +751,9 @@ describe('Type System: build schema from introspection', () => { ({ name }) => name === 'Query', ); - expect(queryTypeIntrospection).to.have.nested.property('fields[0].args'); - delete (queryTypeIntrospection: any).fields[0].args; + invariant(queryTypeIntrospection?.kind === 'OBJECT'); + // $FlowExpectedError[cannot-write] + delete queryTypeIntrospection.fields[0].args; expect(() => buildClientSchema(introspection)).to.throw( /Introspection result missing field args: { name: "foo", .* }\./, @@ -754,11 +766,13 @@ describe('Type System: build schema from introspection', () => { ({ name }) => name === 'Query', ); - expect(queryTypeIntrospection).to.have.nested.property( - 'fields[0].args[0].type.name', - 'String', - ); - (queryTypeIntrospection: any).fields[0].args[0].type.name = 'SomeUnion'; + invariant(queryTypeIntrospection?.kind === 'OBJECT'); + const argType = queryTypeIntrospection.fields[0].args[0].type; + invariant(argType.kind === 'SCALAR'); + + expect(argType).to.have.property('name', 'String'); + // $FlowExpectedError[cannot-write] + argType.name = 'SomeUnion'; expect(() => buildClientSchema(introspection)).to.throw( 'Introspection must provide input type for arguments, but received: SomeUnion.', @@ -771,11 +785,13 @@ describe('Type System: build schema from introspection', () => { ({ name }) => name === 'Query', ); - expect(queryTypeIntrospection).to.have.nested.property( - 'fields[0].type.name', - 'String', - ); - (queryTypeIntrospection: any).fields[0].type.name = 'SomeInputObject'; + invariant(queryTypeIntrospection?.kind === 'OBJECT'); + const fieldType = queryTypeIntrospection.fields[0].type; + invariant(fieldType.kind === 'SCALAR'); + + expect(fieldType).to.have.property('name', 'String'); + // $FlowExpectedError[cannot-write] + fieldType.name = 'SomeInputObject'; expect(() => buildClientSchema(introspection)).to.throw( 'Introspection must provide output type for fields, but received: SomeInputObject.', @@ -788,8 +804,9 @@ describe('Type System: build schema from introspection', () => { ({ name }) => name === 'SomeUnion', ); - expect(someUnionIntrospection).to.have.property('possibleTypes'); - delete (someUnionIntrospection: any).possibleTypes; + invariant(someUnionIntrospection?.kind === 'UNION'); + // $FlowExpectedError[cannot-write] + delete someUnionIntrospection.possibleTypes; expect(() => buildClientSchema(introspection)).to.throw( /Introspection result missing possibleTypes: { kind: "UNION", name: "SomeUnion",.* }\./, @@ -802,8 +819,9 @@ describe('Type System: build schema from introspection', () => { ({ name }) => name === 'SomeEnum', ); - expect(someEnumIntrospection).to.have.property('enumValues'); - delete (someEnumIntrospection: any).enumValues; + invariant(someEnumIntrospection?.kind === 'ENUM'); + // $FlowExpectedError[cannot-write] + delete someEnumIntrospection.enumValues; expect(() => buildClientSchema(introspection)).to.throw( /Introspection result missing enumValues: { kind: "ENUM", name: "SomeEnum", .* }\./, @@ -816,8 +834,9 @@ describe('Type System: build schema from introspection', () => { ({ name }) => name === 'SomeInputObject', ); - expect(someInputObjectIntrospection).to.have.property('inputFields'); - delete (someInputObjectIntrospection: any).inputFields; + invariant(someInputObjectIntrospection?.kind === 'INPUT_OBJECT'); + // $FlowExpectedError[cannot-write] + delete someInputObjectIntrospection.inputFields; expect(() => buildClientSchema(introspection)).to.throw( /Introspection result missing inputFields: { kind: "INPUT_OBJECT", name: "SomeInputObject", .* }\./, @@ -832,7 +851,9 @@ describe('Type System: build schema from introspection', () => { name: 'SomeDirective', locations: ['QUERY'], }); - delete (someDirectiveIntrospection: any).locations; + + // $FlowExpectedError[cannot-write] + delete someDirectiveIntrospection.locations; expect(() => buildClientSchema(introspection)).to.throw( /Introspection result missing directive locations: { name: "SomeDirective", .* }\./, @@ -847,7 +868,9 @@ describe('Type System: build schema from introspection', () => { name: 'SomeDirective', args: [], }); - delete (someDirectiveIntrospection: any).args; + + // $FlowExpectedError[cannot-write] + delete someDirectiveIntrospection.args; expect(() => buildClientSchema(introspection)).to.throw( /Introspection result missing directive args: { name: "SomeDirective", .* }\./, diff --git a/src/utilities/__tests__/coerceInputValue-test.js b/src/utilities/__tests__/coerceInputValue-test.js index 61046b82d9..a5aa72096c 100644 --- a/src/utilities/__tests__/coerceInputValue-test.js +++ b/src/utilities/__tests__/coerceInputValue-test.js @@ -15,29 +15,38 @@ import { import { coerceInputValue } from '../coerceInputValue'; -function expectValue(result: any) { +type CoerceResult = {| + value: mixed, + errors: $ReadOnlyArray<{| + path: $ReadOnlyArray, + value: mixed, + error: string, + |}>, +|}; + +function coerceValue(inputValue: mixed, type: GraphQLInputType): CoerceResult { + const errors = []; + const value = coerceInputValue( + inputValue, + type, + (path, invalidValue, error) => { + errors.push({ path, value: invalidValue, error: error.message }); + }, + ); + + return { errors, value }; +} + +function expectValue(result: CoerceResult) { expect(result.errors).to.deep.equal([]); return expect(result.value); } -function expectErrors(result: any) { +function expectErrors(result: CoerceResult) { return expect(result.errors); } describe('coerceInputValue', () => { - function coerceValue(inputValue: mixed, type: GraphQLInputType) { - const errors = []; - const value = coerceInputValue( - inputValue, - type, - (path, invalidValue, error) => { - errors.push({ path, value: invalidValue, error: error.message }); - }, - ); - - return { errors, value }; - } - describe('for GraphQLNonNull', () => { const TestNonNull = new GraphQLNonNull(GraphQLInt); diff --git a/src/utilities/buildASTSchema.js b/src/utilities/buildASTSchema.js index ab3ae1b6aa..aa2624b3bf 100644 --- a/src/utilities/buildASTSchema.js +++ b/src/utilities/buildASTSchema.js @@ -65,13 +65,16 @@ export function buildASTSchema( // typed values below, that would throw immediately while type system // validation with validateSchema() will produce more actionable results. case 'Query': - config.query = (type: any); + // $FlowExpectedError[incompatible-type] validated in `validateSchema` + config.query = type; break; case 'Mutation': - config.mutation = (type: any); + // $FlowExpectedError[incompatible-type] validated in `validateSchema` + config.mutation = type; break; case 'Subscription': - config.subscription = (type: any); + // $FlowExpectedError[incompatible-type] validated in `validateSchema` + config.subscription = type; break; } } diff --git a/src/utilities/extendSchema.js b/src/utilities/extendSchema.js index 71be143ca8..4aeac58584 100644 --- a/src/utilities/extendSchema.js +++ b/src/utilities/extendSchema.js @@ -4,7 +4,6 @@ import { mapValue } from '../jsutils/mapValue'; import { invariant } from '../jsutils/invariant'; import { devAssert } from '../jsutils/devAssert'; -import type { DirectiveLocationEnum } from '../language/directiveLocation'; import type { DocumentNode, TypeNode, @@ -233,7 +232,7 @@ export function extendSchemaImpl( // Note: While this could make early assertions to get the correctly // typed values, that would throw immediately while type system // validation with validateSchema() will produce more actionable results. - return ((typeMap[type.name]: any): T); + return typeMap[type.name]; } function replaceDirective(directive: GraphQLDirective): GraphQLDirective { @@ -412,7 +411,9 @@ export function extendSchemaImpl( // Note: While this could make early assertions to get the correctly // typed values below, that would throw immediately while type system // validation with validateSchema() will produce more actionable results. - return (opTypes: any); + // $FlowFixMe[incompatible-return] + // $FlowFixMe[incompatible-exact] + return opTypes; } function getNamedType(node: NamedTypeNode): GraphQLNamedType { @@ -437,14 +438,11 @@ export function extendSchemaImpl( } function buildDirective(node: DirectiveDefinitionNode): GraphQLDirective { - const locations = node.locations.map( - ({ value }) => ((value: any): DirectiveLocationEnum), - ); - return new GraphQLDirective({ name: node.name.value, description: node.description?.value, - locations, + // $FlowFixMe[incompatible-call] + locations: node.locations.map(({ value }) => value), isRepeatable: node.repeatable, args: buildArgumentMap(node.arguments), astNode: node, @@ -469,7 +467,7 @@ export function extendSchemaImpl( // Note: While this could make assertions to get the correctly typed // value, that would throw immediately while type system validation // with validateSchema() will produce more actionable results. - type: (getWrappedType(field.type): any), + type: getWrappedType(field.type), description: field.description?.value, args: buildArgumentMap(field.arguments), deprecationReason: getDeprecationReason(field), @@ -559,48 +557,35 @@ export function extendSchemaImpl( | ObjectTypeExtensionNode, >, ): Array { - const interfaces = []; - for (const node of nodes) { + // Note: While this could make assertions to get the correctly typed + // values below, that would throw immediately while type system + // validation with validateSchema() will produce more actionable results. + // $FlowFixMe[incompatible-return] + return nodes.flatMap( // istanbul ignore next (See: 'https://github.com/graphql/graphql-js/issues/2203') - const interfacesNodes = node.interfaces ?? []; - - for (const type of interfacesNodes) { - // Note: While this could make assertions to get the correctly typed - // values below, that would throw immediately while type system - // validation with validateSchema() will produce more actionable - // results. - interfaces.push((getNamedType(type): any)); - } - } - return interfaces; + (node) => node.interfaces?.map(getNamedType) ?? [], + ); } function buildUnionTypes( nodes: $ReadOnlyArray, ): Array { - const types = []; - for (const node of nodes) { + // Note: While this could make assertions to get the correctly typed + // values below, that would throw immediately while type system + // validation with validateSchema() will produce more actionable results. + // $FlowFixMe[incompatible-return] + return nodes.flatMap( // istanbul ignore next (See: 'https://github.com/graphql/graphql-js/issues/2203') - const typeNodes = node.types ?? []; - - for (const type of typeNodes) { - // Note: While this could make assertions to get the correctly typed - // values below, that would throw immediately while type system - // validation with validateSchema() will produce more actionable - // results. - types.push((getNamedType(type): any)); - } - } - return types; + (node) => node.types?.map(getNamedType) ?? [], + ); } function buildType(astNode: TypeDefinitionNode): GraphQLNamedType { const name = astNode.name.value; - const extensionNodes = typeExtensionsMap[name] ?? []; + const extensionASTNodes = typeExtensionsMap[name] ?? []; switch (astNode.kind) { case Kind.OBJECT_TYPE_DEFINITION: { - const extensionASTNodes = (extensionNodes: any); const allNodes = [astNode, ...extensionASTNodes]; return new GraphQLObjectType({ @@ -613,7 +598,6 @@ export function extendSchemaImpl( }); } case Kind.INTERFACE_TYPE_DEFINITION: { - const extensionASTNodes = (extensionNodes: any); const allNodes = [astNode, ...extensionASTNodes]; return new GraphQLInterfaceType({ @@ -626,7 +610,6 @@ export function extendSchemaImpl( }); } case Kind.ENUM_TYPE_DEFINITION: { - const extensionASTNodes = (extensionNodes: any); const allNodes = [astNode, ...extensionASTNodes]; return new GraphQLEnumType({ @@ -638,7 +621,6 @@ export function extendSchemaImpl( }); } case Kind.UNION_TYPE_DEFINITION: { - const extensionASTNodes = (extensionNodes: any); const allNodes = [astNode, ...extensionASTNodes]; return new GraphQLUnionType({ @@ -650,8 +632,6 @@ export function extendSchemaImpl( }); } case Kind.SCALAR_TYPE_DEFINITION: { - const extensionASTNodes = (extensionNodes: any); - return new GraphQLScalarType({ name, description: astNode.description?.value, @@ -661,7 +641,6 @@ export function extendSchemaImpl( }); } case Kind.INPUT_OBJECT_TYPE_DEFINITION: { - const extensionASTNodes = (extensionNodes: any); const allNodes = [astNode, ...extensionASTNodes]; return new GraphQLInputObjectType({ @@ -698,7 +677,8 @@ function getDeprecationReason( | InputValueDefinitionNode, ): ?string { const deprecated = getDirectiveValues(GraphQLDeprecatedDirective, node); - return (deprecated?.reason: any); + // $FlowExpectedError[incompatible-return] validated by `getDirectiveValues` + return deprecated?.reason; } /** @@ -708,5 +688,6 @@ function getSpecifiedByURL( node: ScalarTypeDefinitionNode | ScalarTypeExtensionNode, ): ?string { const specifiedBy = getDirectiveValues(GraphQLSpecifiedByDirective, node); - return (specifiedBy?.url: any); + // $FlowExpectedError[incompatible-return] validated by `getDirectiveValues` + return specifiedBy?.url; } diff --git a/src/utilities/findBreakingChanges.js b/src/utilities/findBreakingChanges.js index 2a13d4655b..d259d3b510 100644 --- a/src/utilities/findBreakingChanges.js +++ b/src/utilities/findBreakingChanges.js @@ -81,10 +81,10 @@ export function findBreakingChanges( oldSchema: GraphQLSchema, newSchema: GraphQLSchema, ): Array { - const breakingChanges = findSchemaChanges(oldSchema, newSchema).filter( + // $FlowFixMe[prop-missing] + return findSchemaChanges(oldSchema, newSchema).filter( (change) => change.type in BreakingChangeType, ); - return ((breakingChanges: any): Array); } /** @@ -95,10 +95,10 @@ export function findDangerousChanges( oldSchema: GraphQLSchema, newSchema: GraphQLSchema, ): Array { - const dangerousChanges = findSchemaChanges(oldSchema, newSchema).filter( + // $FlowFixMe[prop-missing] + return findSchemaChanges(oldSchema, newSchema).filter( (change) => change.type in DangerousChangeType, ); - return ((dangerousChanges: any): Array); } function findSchemaChanges( diff --git a/src/utilities/introspectionFromSchema.js b/src/utilities/introspectionFromSchema.js index 782faca0a0..8d30e9bce6 100644 --- a/src/utilities/introspectionFromSchema.js +++ b/src/utilities/introspectionFromSchema.js @@ -36,5 +36,7 @@ export function introspectionFromSchema( const document = parse(getIntrospectionQuery(optionsWithDefaults)); const result = executeSync({ schema, document }); invariant(!result.errors && result.data); - return (result.data: any); + // $FlowIgnore[incompatible-indexer] + // $FlowIgnore[incompatible-return] + return result.data; } diff --git a/src/utilities/lexicographicSortSchema.js b/src/utilities/lexicographicSortSchema.js index 30c0e44807..291248ec1a 100644 --- a/src/utilities/lexicographicSortSchema.js +++ b/src/utilities/lexicographicSortSchema.js @@ -66,7 +66,8 @@ export function lexicographicSortSchema(schema: GraphQLSchema): GraphQLSchema { } function replaceNamedType(type: T): T { - return ((typeMap[type.name]: any): T); + // $FlowFixMe[incompatible-return] + return typeMap[type.name]; } function replaceMaybeType(maybeType: T): T {