Skip to content

Commit

Permalink
prevent infinite recursion of ContainsFragmentsRefs type
Browse files Browse the repository at this point in the history
  • Loading branch information
phryneas committed Dec 12, 2024
1 parent 851deb0 commit 2614ce8
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 7 deletions.
15 changes: 15 additions & 0 deletions src/masking/__benches__/types.bench.ts
Original file line number Diff line number Diff line change
Expand Up @@ -577,3 +577,18 @@ test("detects `$fragmentRefs` on types with index signatures", (prefix) => {
}>();
});
});

test("recursive types: no error 'Type instantiation is excessively deep and possibly infinite.'", (prefix) => {
// this type is self-recursive
type Source = import("graphql").IntrospectionQuery;

bench(prefix + "instantiations", () => {
return {} as MaybeMasked<Source>;
}).types([6, "instantiations"]);

bench(prefix + "functionality", () => {
const x = {} as MaybeMasked<Source>;

expectTypeOf(x).branded.toEqualTypeOf<Source>();
});
});
17 changes: 10 additions & 7 deletions src/masking/internal/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,10 +182,13 @@ export type RemoveMaskedMarker<T> = Omit<T, "__masked">;
export type RemoveFragmentName<T> =
T extends any ? Omit<T, " $fragmentName"> : T;

export type ContainsFragmentsRefs<TData> =
true extends IsAny<TData> ? false
: TData extends object ?
" $fragmentRefs" extends keyof RemoveIndexSignature<TData> ?
true
: ContainsFragmentsRefs<TData[keyof TData]>
: false;
type Exact<in out T> = (x: T) => T;
export type ContainsFragmentsRefs<TData, Seen = never> = true extends (
IsAny<TData>
) ?
false
: TData extends object ?
Exact<TData> extends Seen ? false
: " $fragmentRefs" extends keyof RemoveIndexSignature<TData> ? true
: ContainsFragmentsRefs<TData[keyof TData], Seen | Exact<TData>>
: false;

0 comments on commit 2614ce8

Please sign in to comment.