diff --git a/.changeset/free-fans-dance.md b/.changeset/free-fans-dance.md new file mode 100644 index 00000000000..98ba2044441 --- /dev/null +++ b/.changeset/free-fans-dance.md @@ -0,0 +1,6 @@ +--- +'@graphql-codegen/visitor-plugin-common': patch +'@graphql-codegen/typescript-operations': patch +--- + +Add printTypeScriptType to handle printing TS types, as there are special cases like `any` and `unknown` diff --git a/packages/plugins/other/visitor-plugin-common/src/utils.ts b/packages/plugins/other/visitor-plugin-common/src/utils.ts index fd76f75e850..72476c049a9 100644 --- a/packages/plugins/other/visitor-plugin-common/src/utils.ts +++ b/packages/plugins/other/visitor-plugin-common/src/utils.ts @@ -687,3 +687,31 @@ const getDeprecationReason = (directive: DirectiveNode): string | void => { return reason; } }; + +/** + * @description Utility function to print a TypeScript type. + * We need this since some TypeScript types have special handling. + * e.g. `unknown | null | undefined` is treated as `unknown` + * + * Note: we currently have two types of handling nullable: `Maybe` or `T | null | undefined` + * This function only handles the latter case at the moment, but could be extended if needed. + */ +export const printTypeScriptType = ({ + type, + isNullable, + nullableSuffix, +}: { + type: string; + nullableSuffix: string; + isNullable: boolean; +}): string => { + if (type === 'any' || type === 'unknown') { + return type; + } + + if (isNullable) { + return `${type}${nullableSuffix}`; + } + + return type; +}; diff --git a/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts b/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts index cee63b694f2..87e332fe849 100644 --- a/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts +++ b/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts @@ -4,6 +4,7 @@ import { NormalizedAvoidOptionalsConfig, NormalizedScalarsMap, ParsedEnumValuesMap, + printTypeScriptType, } from '@graphql-codegen/visitor-plugin-common'; import { Kind, TypeNode } from 'graphql'; @@ -96,6 +97,8 @@ export class TypeScriptOperationVariablesToObject extends OperationVariablesToOb protected wrapMaybe(type: string): string { const maybeSuffix = this._config.inputMaybeValueSuffix; - return type.endsWith(maybeSuffix) ? type : `${type}${maybeSuffix}`; + return type.endsWith(maybeSuffix) + ? type + : printTypeScriptType({ type, isNullable: true, nullableSuffix: maybeSuffix }); } } diff --git a/packages/plugins/typescript/operations/src/visitor.ts b/packages/plugins/typescript/operations/src/visitor.ts index 64ef7954336..969c95d9c8d 100644 --- a/packages/plugins/typescript/operations/src/visitor.ts +++ b/packages/plugins/typescript/operations/src/visitor.ts @@ -22,6 +22,7 @@ import { SelectionSetToObject, getNodeComment, wrapTypeWithModifiers, + printTypeScriptType, } from '@graphql-codegen/visitor-plugin-common'; import { normalizeImportExtension } from '@graphql-codegen/plugin-helpers'; import autoBind from 'auto-bind'; @@ -277,7 +278,11 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< typePart = usedInputType.tsType; // If the schema is correct, when reversing typeNodes, the first node would be `NamedType`, which means we can safely set it as the base for typePart if (!typeNode.isNonNullable) { - typePart += this._inputMaybeValueSuffix; + typePart = printTypeScriptType({ + type: typePart, + isNullable: true, + nullableSuffix: this._inputMaybeValueSuffix, + }); } continue; } @@ -285,7 +290,11 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< if (typeNode.type === 'ListType') { typePart = `Array<${typePart}>`; if (!typeNode.isNonNullable) { - typePart += this._inputMaybeValueSuffix; + typePart = printTypeScriptType({ + type: typePart, + isNullable: true, + nullableSuffix: this._inputMaybeValueSuffix, + }); } } } diff --git a/packages/plugins/typescript/operations/tests/ts-documents.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.spec.ts index c596eaec2a6..e9a6660569c 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.spec.ts @@ -2749,7 +2749,7 @@ export type Q2Query = { search: Array< expect(content).toMatchInlineSnapshot( ` "export type TestQueryQueryVariables = Exact<{ - test?: unknown | null | undefined; + test?: unknown; }>; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.default-scalar-types.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.default-scalar-types.spec.ts index ecb60c75d73..3781cd5b31e 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.default-scalar-types.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.default-scalar-types.spec.ts @@ -70,18 +70,18 @@ describe('TypeScript Operations Plugin - Default Scalar types', () => { export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; type UserInput = { nonNullableDate: unknown; - nullableDate?: unknown | null | undefined; - dateArray1?: Array | null | undefined; - dateArray2: Array; + nullableDate?: unknown; + dateArray1?: Array | null | undefined; + dateArray2: Array; dateArray3?: Array | null | undefined; dateArray4: Array; }; export type UserQueryVariables = Exact<{ nonNullableDate: unknown; - nullableDate?: unknown | null | undefined; - dateArray1?: Array | unknown | null | undefined; - dateArray2: Array | unknown; + nullableDate?: unknown; + dateArray1?: Array | unknown | null | undefined; + dateArray2: Array | unknown; dateArray3?: Array | unknown | null | undefined; dateArray4: Array | unknown; input: UserInput; @@ -163,18 +163,18 @@ describe('TypeScript Operations Plugin - Default Scalar types', () => { export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; type UserInput = { nonNullableDate: any; - nullableDate?: any | null | undefined; - dateArray1?: Array | null | undefined; - dateArray2: Array; + nullableDate?: any; + dateArray1?: Array | null | undefined; + dateArray2: Array; dateArray3?: Array | null | undefined; dateArray4: Array; }; export type UserQueryVariables = Exact<{ nonNullableDate: any; - nullableDate?: any | null | undefined; - dateArray1?: Array | any | null | undefined; - dateArray2: Array | any; + nullableDate?: any; + dateArray1?: Array | any | null | undefined; + dateArray2: Array | any; dateArray3?: Array | any | null | undefined; dateArray4: Array | any; input: UserInput; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts index 7f09e1440d0..a75ebd0f397 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts @@ -110,9 +110,9 @@ describe('TypeScript Operations Plugin - Import Types', () => { /** UsersInput Description */ type UsersInput = { /** UsersInput from */ - from?: unknown | null | undefined; + from?: unknown; /** UsersInput to */ - to?: unknown | null | undefined; + to?: unknown; role?: UserRole | null | undefined; }; @@ -135,7 +135,7 @@ describe('TypeScript Operations Plugin - Import Types', () => { export type UsersWithScalarInputQueryVariables = Exact<{ from: unknown; - to?: unknown | null | undefined; + to?: unknown; role?: TypeImport.UserRole | null | undefined; }>; @@ -254,9 +254,9 @@ describe('TypeScript Operations Plugin - Import Types', () => { /** UsersInput Description */ type UsersInput = { /** UsersInput from */ - from?: unknown | null | undefined; + from?: unknown; /** UsersInput to */ - to?: unknown | null | undefined; + to?: unknown; role?: UserRole | null | undefined; }; @@ -279,7 +279,7 @@ describe('TypeScript Operations Plugin - Import Types', () => { export type UsersWithScalarInputQueryVariables = Exact<{ from: unknown; - to?: unknown | null | undefined; + to?: unknown; role?: TypeImport.UserRole | null | undefined; }>; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts index a67c55b8f09..a6cc40fd9e2 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts @@ -102,7 +102,7 @@ describe('TypeScript Operations Plugin - Input', () => { from?: Date | null | undefined; /** UsersInput to */ to?: Date | null | undefined; - timezone?: unknown | null | undefined; + timezone?: unknown; role?: UserRole | null | undefined; ageRange1?: Array | null | undefined; ageRange2: Array; @@ -219,7 +219,7 @@ describe('TypeScript Operations Plugin - Input', () => { readonly from?: Date | null | undefined; /** UsersInput to */ readonly to?: Date | null | undefined; - readonly timezone?: unknown | null | undefined; + readonly timezone?: unknown; readonly role?: UserRole | null | undefined; readonly ageRange1?: Array | null | undefined; readonly ageRange2: Array; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts index 45f5fc3f578..f048786fee7 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts @@ -138,9 +138,9 @@ describe('TypeScript Operations Plugin - Standalone', () => { /** UsersInput Description */ type UsersInput = { /** UsersInput from */ - from?: unknown | null | undefined; + from?: unknown; /** UsersInput to */ - to?: unknown | null | undefined; + to?: unknown; role?: UserRole | null | undefined; }; @@ -163,7 +163,7 @@ describe('TypeScript Operations Plugin - Standalone', () => { export type UsersWithScalarInputQueryVariables = Exact<{ from: unknown; - to?: unknown | null | undefined; + to?: unknown; role?: UserRole | null | undefined; }>; @@ -654,9 +654,9 @@ describe('TypeScript Operations Plugin - Standalone', () => { /** UsersInput Description */ type UsersInput = { /** UsersInput from */ - from?: unknown | null | undefined; + from?: unknown; /** UsersInput to */ - to?: unknown | null | undefined; + to?: unknown; role?: UserRole | null | undefined; }; "