I want to write a function f
that accepts a single argument of type A
, where A
must be an array that contains an element of a certain type T
. For simplicity, assume that T = 'ok'
(singleton type of the string 'ok'
).
Using the idea from this answer, I obtained the following preliminary solution:
function f<
E,
A extends (ReadonlyArray<E> | [E]) & {[K in keyof A]: {[T in K]: 'ok'}}[number]
>(a: A) {}
As in the answer quoted above, it indeed works.
But I could not make any sense of the | [E]
-part, so I decided to check whether I can remove it, or replace it by yet another type:
function f<
E,
X,
A extends (ReadonlyArray<E> | [X]) & {[K in keyof A]: {[T in K]: 'ok'}}[number]
>(a: A) {}
This also works, i.e. it can differentiate between arrays with or without element 'ok'
:
f(['a', 'b', 'ok', 'z']) // compiles, good
f(['a', 'b', 'z']) // does not compile, good
My problem is that I can't understand why it doesn't work if I remove the [X]
part. It seems completely unrelated to anything what's going on in the code:
- Arity of
[X]
does not match the arity of the tuples - The type
X
isn't actually tied to anything, it has no bounds containing eitherE
orA
orstring
or'ok'
or anything else.
What is the | [X]
doing, exactly?