This just occured to me as I was playing around with API design in my head. In short, is there a way to define a type like this?
type SpecialArray<Unique, Bland> = [...Bland[], Unique, ...Bland[]];
But this of course gives me "A rest element cannot follow another rest element".
The closest I can get to is:
type SpecialArray<Unique, Bland> = [...Bland[], Unique] | [Unique, ...Bland[]];
which only allows the "unique" element to be first or last in the array. Note that this implies that the array must contain at least one element as well (the unique one).
Yes I have seen Typescript: only allow one occurrence of a value in an array, but the solutions do not work for any length, and I was unable to find any other resource on this problem. I am aware that I can write a helper function to enforce/infer the type for me, like this:
type Count<A extends readonly any[], T, Counter extends any[] = []> = A extends [infer H, ...infer R] ? [H] extends [T] ? Count<R, T, [...Counter, H]> : Count<R, T, Counter> : Counter;
type IsSpecial<A extends readonly any[], Unique, Bland> =
Count<A, Unique>["length"] extends 1
? A[number] extends Unique | Bland
? A
: never
: never;
function helper<A extends readonly any[]>(array: IsSpecial<[...A], string, number>) { return array; }
What I'd like is a type that I can use like this instead:
const checked: SpecialArray<string, number> = [...];
Is it possible?
I will accept a solution to SpecialArray<Unique, Bland>
, a workaround that is different from mine or betters mine in some way, or plain "no" and why it's not possible.
Partial (80%