Below is a simplified version of the code causing the problem:
type Head<T> = T extends [infer U,...unknown[]] ? U : never;
type Tail<T> = T extends [unknown,...infer U] ? U : [];
type Converter = null;
type Convert<T, U extends Converter> = T;
type ConvChain<BaseType, T extends Converter[]> =
T extends [Converter]
? Convert<BaseType, Head<T>>
: Head<T> extends Converter
? ConvChain<Convert<BaseType, Head<T>>, Tail<T>>
: never;
type ThisWillBeError = ConvChain<unknown, Converter[]>;
The type ThisWillBeError
is expected to throw this error message:
Type instantiation is excessively deep and possibly infinite.
The goal is to resolve this error.
Code Explanation
Head<T>
... Retrieves the first element of an array
Tail<T>
... Retrieves all elements of an array except the first one.
Convert<T, U extends Converter>
/ Converter
...Applies a specific transformation indicated by type
U
to type T
.
The complex type structure used here was intentional in order to reproduce the issue where returning T
regardless of directive type U</code still triggers the error.<br />
The instruction-giving type <code>U
must also satisfy the Converter
type.
ConvChain
...
Successively applies converters provided in type "T" to the BaseType.
Example:
ConvChain<Test, [A, B, C]>
=
Convert<Convert<Convert<Test, A>, B>, C>
Importance of Type ThisWillBeError
To achieve the same functionality as the type "Convert," it seems necessary to create a generic function like this:
function someFunc<Convs extends Converter[], Base>(x: Base, convs: Convs): ConvChain<Base, Convs> {
return /* result */ as ConvChain<Base, Convs>;
}
The usage of ConvChain<Base, Convs>
leads to the same aforementioned error. It appears these issues stem from the same source.
Attempts Made
I hypothesized that there might be a limit on the number of array elements that can be passed to a ConvChain
(a recursive type).
Thus, I created the following set up restricting to five or fewer Converters:
type ThisWillBeError = ConvChain<unknown, [
...([Converter] | []),
...([Converter] | []),
...([Converter] | []),
...([Converter] | []),
...([Converter] | []),
]>;
Although this still resulted in an error, it strangely worked correctly when limited to accepting 1 to 5 parameters.
type ThisWorks = ConvChain<unknown, [
Converter,
...([Converter] | []),
...([Converter] | []),
...([Converter] | []),
...([Converter] | []),
]>;
Ideally, I would prefer to allow for empty arrays with Converter
and remove any preset maximum limit.
(In other words, encountering an error should only happen if an array surpasses the TypeScript limit within the function's generics.)
Additional Details
I am using Typescript version 4.8.4.
This issue has been replicated across versions 4.2.3 to 4.9.4.
(I'm a Japanese student, please forgive any mistakes in my English!)