Repository navigation
"Type instantiation is excessively deep and possibly infinite" and tsc crashing #891
Copy link
Copy link
Closed
Labels
Description
Describe the bug
First off, thanks for the awesome library!
We have been observing some weird instances of "Type instantiation is excessively deep and possibly infinite". For some files, tsc is even crashing.
Our repo is private so can't share it but we created a couple of custom Fields/components, so maybe you can spot where this is coming from:
- We have been using zod as a form validator on Fields
- We wrap all forms in a form context provider to avoid prop drilling and are passing in reference from useRef(form) as we had some problems with stability in earlier versions (not sure if this still makes any difference).
Code
import type { MutableRefObject } from "react";
import { createContext, useContext } from "react";
import type { useForm } from "@tanstack/react-form";
export const FormContext: React.Context<MutableRefObject<ReturnType<typeof useForm<any>>> | undefined> =
createContext<MutableRefObject<ReturnType<typeof useForm<any>>> | undefined>(undefined);
export function useFormContext<V>(): ReturnType<typeof useForm<V>> {
const form = useContext(FormContext) as MutableRefObject<ReturnType<typeof useForm<V>>> | undefined;
if (!form) {
throw new Error("useFormContext must be used within a FormProvider");
}
return form.current;
}- We are using custom fields like in the code below
Code
type IsDeepValueString<T, K extends DeepKeys<T>> = DeepValue<T, K> extends string | number | typeof Any
? K
: never;
type StringDeepKeys<T> = {
[P in DeepKeys<T>]: IsDeepValueString<T, P>;
}[DeepKeys<T>];
export const TextField = <V, N extends DeepKeys<V> & StringDeepKeys<V>>(
props: {
name: N;
label?: string;
regexPattern?: string;
rightElement?: ReactNode;
isPassword?: boolean;
extraFieldProps?: Omit<FieldOptions<V, N, any>, "name">;
} & Omit<InputProps, "name" | "label">,
): ReactNode => {
const form = useFormContext<V>();
const { name, label, regexPattern, rightElement, isPassword, ...rest } = props;
return (
<form.Field {...props.extraFieldProps} name={props.name}>
{(field) => {
console.log("ruleAsset", props.name, field.getValue());
return (
<FormControl isInvalid={field.state.meta.isTouched && field.state.meta.errors?.length > 0}>
{props.label && <FormLabel htmlFor={String(props.name)}>{props.label}</FormLabel>}
<InputGroup>
<Input
type={props.isPassword ? "password" : "text"}
value={field.getValue() === Any ? "∞" : (field.getValue() as string)}
name={String(field.name)}
onChange={(e) => {
console.log("ruleasset ruleamount change", e.target.value);
const regex = new RegExp(props.regexPattern ?? "");
console.log("1");
if (e.target.value === "" || !props.regexPattern || regex.test(e.target.value)) {
console.log("2");
//need to cast as we extend string so its not sure it can be assinged properly
field.handleChange(e.target.value as DeepValue<V, N>);
console.log("2.1");
} else if (e.target.value === "∞") {
field.handleChange(Any as DeepValue<V, N>);
}
console.log("3");
}}
onBlur={field.handleBlur}
{...rest}
/>
{props.rightElement !== undefined && <InputRightElement>{props.rightElement}</InputRightElement>}
</InputGroup>
<FormErrorMessage>
{field.state.meta.isTouched && field.state.meta.errors?.join(", ")}
</FormErrorMessage>
</FormControl>
);
}}
</form.Field>
);
};- We are using some fields where we receive the value from a query. We want to run validation on it and use it with other fields so we decided for the below structure:
Code
export const GasEstimateSimulation = ({
gasField,
metaData,
userCoin,
approval,
}: {
gasField: FieldApi<RequestTransactionValues, FormField.Gas, any>;
metaData: CoinsData | undefined;
userCoin: UserCoin | undefined;
approval: Approval<UserRequestType.RequestTransaction>;
}): ReactNode => {
const currentWorkspace = useCurrentWorkspace();
const assets = useAssets(currentWorkspace);
const estimatedGas = useEstimateGas(getEstimateGasArgsFromApproval(approval));
console.log("Estimate gas error", estimatedGas, getEstimateGasArgsFromApproval(approval));
useEffect(() => {
console.log("setting gas", estimatedGas.data);
if (estimatedGas.data !== gasField.getValue()) {
gasField.handleChange(estimatedGas.data);
}
}, [estimatedGas.data, gasField]);
return (
<TransactionFeeCardFromGasResult
gas={estimatedGas}
network={getNetworkFromApproval(approval)}
userCoin={userCoin}
metaData={metaData}
// isLoading={!assets.isSuccess || !estimatedGas.isSuccess}
fontSize="xs"
// error={estimatedGas.error}
/>
);
};Your minimal, reproducible example
Steps to reproduce
See examples above
Expected behavior
Less performance issues with type checking
How often does this bug happen?
None
Screenshots or Videos
No response
Platform
macOs
TanStack Form adapter
None
TanStack Form version
0.26.4
TypeScript version
5.5.4
Additional context
We are using the zod form adaptor at the same version (0.26.4)
Reactions are currently unavailable
Activity
singhparshant commentedon Aug 9, 2024
Following
Balastrong commentedon Aug 11, 2024
First thing I'd try is to replace the temporary workaround
ReturnType<typeof useForm<V>>with the newly exposedReactFormApi<V>, in other similar cases this helped already with the type issue.If that doesn't work, could you please reproduce the case on a stackblitz? You can fork one from the docs (e.g. https://tanstack.com/form/latest/docs/framework/react/examples/simple)
Speaking of custom components, we've been drafting a possible API and recommended pattern in #825 (component example in https://github.com/TanStack/form/pull/825/files#diff-b2e0803ded7363bf3432f160f7c7f6e9bf4f982ad13b08ecb4789c228774f956).
Since you're doing something similar your feedback can help shaping the final version :)
fl0ydj commentedon Aug 11, 2024
Changed it to
ReactFormApi<V> & FormApi<V>. Didn't fix the issue though.Have been trying to reproduce some of the issues on stackblitz. Have not been able to do so though as it just starts happening once the types are pretty complex.
Found one issue, where I had slightly conflicting generics. i.e.:
Changing
fieldVal1:MyEnum,tofieldVal1:SubEnumType,solved the error in that situation.I have tried reproducing this in the stackblitz but even this didn't work as presumably my test types were too simple.
Concluding, generally it seems that if the formdata types get too complex, its hard to avoid these ts issues?
Will also give it a couple more tries in the next couple of days
favna commentedon Aug 20, 2024
I'm also facing this issue in the project where I'm transitioning from Formik to Tanstack Form so I will likewise try to create a reproducible Stackblitz. So far what I can say is that the error occurs on a function I wrote
setFormFieldValue:Which I call from an
onChangeto set the value of another field. I noticed that if I only usesetFieldValue(without the additional meta) that our Testing Library tests fail because the proper errors aren't shown, coming from this component:The type of the form structure where I call this function is:
And it's called like so:
With the form being:
For the time being I added an
@ts-ignoreon the line that's giving a problem but I do hope this can get fixed some way.If it matters, this is my system info:
Spaubleit commentedon Aug 27, 2024
I recreated the most minimal reproduction possible:
CodeSandbox
It happens in forms with 2 or more fields.
DaliborHomola commentedon Sep 7, 2024
In my case, this problem was caused by having an interface with a property type Moment.
This problem still occurs in the latest version 0.32.0
alexgorbatchev commentedon Nov 6, 2024
This is still happening on
0.34.4.The problem is caused by adding
as string[]totitle: []. The type is necessary for theform.pushFieldValue('title', 'hello');to work, otherwise there's a type error that'hello'is not assignable to parameter of typeneverBalastrong commentedon Nov 12, 2024
Can you give it a try with the version from #1016?
To use it in your projects use this install script:
fl0ydj commentedon Nov 14, 2024
Thanks for looking into it! Still occurring for me though.
Balastrong commentedon Nov 14, 2024
Can you share an example on a stackblitz so I can try to play with it?
fl0ydj commentedon Nov 16, 2024
Had problems reproducing it back then :( I guess it scales with type complexity. Does your fix solve the examples the others provided?
If yes, will give it another try
Balastrong commentedon Nov 16, 2024
The simple example yes, I also added a test for the type here https://github.com/TanStack/form/pull/1016/files#diff-10b547d59824e5f1426565e2505783160a33492805eab90bd86f9d342088bde4R38
xmsz-stu commentedon Dec 4, 2024
saneruby commentedon Dec 5, 2024
crutchcorn commentedon Dec 5, 2024
Hey all, I am sorry but unless you're reporting some new information - please avoid "SAME" or "Facing this problem as well" or whatnot.
We're aware of the issue, but aren't sure the best way to fix it other than suggest "do not use
useField", which is generally our suggestion anyway.saneruby commentedon Dec 5, 2024
I apologize for writing an uninformative comment. I ran into this problem when I tried to use <form.Field/>, when trying to output types, it returns a similar error as the creator of this issue.
Unfortunately, I will not be able to give my repository, since the project is large and it contains confidential data.
I want to note that intellisense works again after I comment out the line with <form.Field/>
saneruby commentedon Dec 14, 2024
is there any news related to the solution of this problem?
epenflow commentedon Jan 29, 2025
I believe this issue arises in typscript when the type system encounters a recursive type definition or an excessively complex type that exceeds its resolution limits. I've experienced a similar error while attempting to output certain types from the intellisense
crutchcorn commentedon Mar 1, 2025
I believe I've fixed the outstanding issues with this TypeScript problem. If you re-run into this problem, please make a minimal reproduction and let me know in a new GH issue.
dan-gamble commentedon Mar 1, 2025
Is there a commit we could look at @crutchcorn?
crutchcorn commentedon Mar 1, 2025
@dan-gamble truthfully I don't know there's a single commit to point to as a fix for this. The strategies in preventing infinite instantiation is that we:
NoInfermore to prevent additional types from being added (Why we had to make TS 5.4 the minimum with the latest minor release)HoaX7 commentedon Oct 8, 2025
im on TS 5.9. im still facing this issue. Also I've noticed this issue is related to zod. When i replaced
zodSchemawith an object i dont get the error