From cdd6370518407296c4307597b1f0df703a5091fd Mon Sep 17 00:00:00 2001 From: Phil Pluckthun Date: Sat, 3 Feb 2024 10:43:37 +0000 Subject: [PATCH] fix: Add tail recursion where it's possible but missing (#51) Co-authored-by: deathemperor Co-authored-by: HaiNNT --- .changeset/short-teachers-begin.md | 5 ++ src/selection.ts | 84 ++++++++++++++++-------------- src/variables.ts | 68 +++++++++++++----------- 3 files changed, 90 insertions(+), 67 deletions(-) create mode 100644 .changeset/short-teachers-begin.md diff --git a/.changeset/short-teachers-begin.md b/.changeset/short-teachers-begin.md new file mode 100644 index 00000000..8daf13e2 --- /dev/null +++ b/.changeset/short-teachers-begin.md @@ -0,0 +1,5 @@ +--- +'gql.tada': patch +--- + +Improve performance of several smaller types (Thank you, [@deathemperor](https://github.com/deathemperor) & [@HaiNNT](https://github.com/HaiNNT)) diff --git a/src/selection.ts b/src/selection.ts index ef5e2242..b6616988 100644 --- a/src/selection.ts +++ b/src/selection.ts @@ -134,45 +134,53 @@ type _getPossibleTypeSelectionRec< Type extends ObjectLikeType, Introspection extends IntrospectionLikeType, Fragments extends { [name: string]: any }, + SelectionAcc = {}, > = Selections extends [infer Node, ...infer Rest] - ? (Node extends { kind: Kind.FRAGMENT_SPREAD | Kind.INLINE_FRAGMENT } - ? getSpreadSubtype extends infer Subtype extends - ObjectLikeType - ? PossibleType extends getTypenameOfType - ? - | (isOptional extends true ? {} : never) - | getFragmentSelection - : {} - : Node extends { kind: Kind.FRAGMENT_SPREAD; name: any } - ? makeUndefinedFragmentRef - : {} - : Node extends { kind: Kind.FIELD; name: any; selectionSet: any } - ? isOptional extends true - ? { - [Prop in getFieldAlias]?: Node['name']['value'] extends '__typename' - ? PossibleType - : unwrapType< - Type['fields'][Node['name']['value']]['type'], - Node['selectionSet'], - Introspection, - Fragments, - getTypeDirective - >; - } - : { - [Prop in getFieldAlias]: Node['name']['value'] extends '__typename' - ? PossibleType - : unwrapType< - Type['fields'][Node['name']['value']]['type'], - Node['selectionSet'], - Introspection, - Fragments, - getTypeDirective - >; - } - : {}) & - _getPossibleTypeSelectionRec - : {}; + ? _getPossibleTypeSelectionRec< + Rest, + PossibleType, + Type, + Introspection, + Fragments, + (Node extends { kind: Kind.FRAGMENT_SPREAD | Kind.INLINE_FRAGMENT } + ? getSpreadSubtype extends infer Subtype extends + ObjectLikeType + ? PossibleType extends getTypenameOfType + ? + | (isOptional extends true ? {} : never) + | getFragmentSelection + : {} + : Node extends { kind: Kind.FRAGMENT_SPREAD; name: any } + ? makeUndefinedFragmentRef + : {} + : Node extends { kind: Kind.FIELD; name: any; selectionSet: any } + ? isOptional extends true + ? { + [Prop in getFieldAlias]?: Node['name']['value'] extends '__typename' + ? PossibleType + : unwrapType< + Type['fields'][Node['name']['value']]['type'], + Node['selectionSet'], + Introspection, + Fragments, + getTypeDirective + >; + } + : { + [Prop in getFieldAlias]: Node['name']['value'] extends '__typename' + ? PossibleType + : unwrapType< + Type['fields'][Node['name']['value']]['type'], + Node['selectionSet'], + Introspection, + Fragments, + getTypeDirective + >; + } + : {}) & + SelectionAcc + > + : SelectionAcc; type getOperationSelectionType< Definition, diff --git a/src/variables.ts b/src/variables.ts index e4e82e21..86e0c82a 100644 --- a/src/variables.ts +++ b/src/variables.ts @@ -6,14 +6,19 @@ import type { obj } from './utils'; type getInputObjectTypeRec< InputFields, Introspection extends IntrospectionLikeType, + InputObject = {}, > = InputFields extends [infer InputField, ...infer Rest] - ? (InputField extends { name: any; type: any } - ? InputField['type'] extends { kind: 'NON_NULL' } - ? { [Name in InputField['name']]: unwrapType } - : { [Name in InputField['name']]?: unwrapType } - : {}) & - getInputObjectTypeRec - : {}; + ? getInputObjectTypeRec< + Rest, + Introspection, + (InputField extends { name: any; type: any } + ? InputField['type'] extends { kind: 'NON_NULL' } + ? { [Name in InputField['name']]: unwrapType } + : { [Name in InputField['name']]?: unwrapType } + : {}) & + InputObject + > + : InputObject; type getScalarType< TypeName, @@ -62,27 +67,32 @@ type unwrapTypeRef = Type ext ? _unwrapTypeRefRec : null | _unwrapTypeRefRec; -type getVariablesRec = Variables extends [ - infer Variable, - ...infer Rest, -] - ? (Variable extends { kind: Kind.VARIABLE_DEFINITION; variable: any; type: any } - ? Variable extends { defaultValue: undefined; type: { kind: Kind.NON_NULL_TYPE } } - ? { - [Name in Variable['variable']['name']['value']]: unwrapTypeRef< - Variable['type'], - Introspection - >; - } - : { - [Name in Variable['variable']['name']['value']]?: unwrapTypeRef< - Variable['type'], - Introspection - >; - } - : {}) & - getVariablesRec - : {}; +type _getVariablesRec< + Variables, + Introspection extends IntrospectionLikeType, + VariablesObject = {}, +> = Variables extends [infer Variable, ...infer Rest] + ? _getVariablesRec< + Rest, + Introspection, + (Variable extends { kind: Kind.VARIABLE_DEFINITION; variable: any; type: any } + ? Variable extends { defaultValue: undefined; type: { kind: Kind.NON_NULL_TYPE } } + ? { + [Name in Variable['variable']['name']['value']]: unwrapTypeRef< + Variable['type'], + Introspection + >; + } + : { + [Name in Variable['variable']['name']['value']]?: unwrapTypeRef< + Variable['type'], + Introspection + >; + } + : {}) & + VariablesObject + > + : VariablesObject; type getVariablesType< Document extends DocumentNodeLike, @@ -91,7 +101,7 @@ type getVariablesType< kind: Kind.OPERATION_DEFINITION; variableDefinitions: any; } - ? obj> + ? obj<_getVariablesRec> : {}; export type { getVariablesType };