user1543574
user1543574

Reputation: 863

How to infer Tuples while preserving type?

Playground

The Code:

type _join<_symbols extends [any, ...string[]]> = {
  [_key in _symbols as _key extends [any, ...infer rest] ? join<rest, '/'> : never]: _key[0];
};

The rest value should be inferred to as string[], but is instead inferred as unknown[]. Why is this? The output works as expected, so the logic should be sound. I'm assuming it's some quirk of TS's syntax I'm missing?

Upvotes: 1

Views: 54

Answers (1)

Tobias S.
Tobias S.

Reputation: 23825

You are right in your assumption that the logic is sound here but are hitting a limitation of the infer keyword.

The information from the constraint of _symbols is not carried over to the inferred type rest as described in #21937. Types inferred from a generic type with the infer keyword often do not have any further information associated with them and appear as opaque generic types.

For this example, the inference of rest is not fully opaque. Since the position of the inference is a variadic tuple type, it is assumed by the compiler that rest must extend unknown[] which is what you see in the error message.


I found this proposal which, if implemented at some point, could give the compiler the ability to also factor in the constraints when inferring types using infer. For now, the need for this feature is limited as PR#48112 introduced a way to explicitly provide a constraint when using the infer keyword.

type _join<_symbols extends [any, ...string[]]> = {
  [_key in _symbols as _key extends [any, ...infer rest extends string[]] 
    ? join<rest, '/'> 
    : never
  ]: _key[0];
};

This is looks to be somewhat redundant; but for the foreseeable future we will need it to solve these issues.


Playground

Upvotes: 2

Related Questions