Typescript version: 5.1.6
Here is a minimal reconstruction of my problem:
I have a function f
which is gonna take an array of C
where
declare class C<a = unknown, b = unknown> {
getA(): a;
getB(): b;
};
The first generic of C
, which is A is going to be an object.
I want to explicitly
get the array of C
as a tuple in the f
declare function f<T extends any[]>(arr: [...T]): any;
declare const a: C<{ name: string }, []>;
declare const b: C<{ name: string }, []>;
f([a, b])
Hovering on the f
we can see exactly what we want.
function f<[C<{
name: string;
}, []>, C<{
name: string;
}, []>]>(arr: [C<{
name: string;
}, []>, C<{
name: string;
}, []>]): any
The problem comes when I want to wrap the array type with another type, which is going to check if there are duplicate keys on the T
.
When I do something like this:
type ExtractObject<I> = I extends C<infer P> ? P : never;
type ExtractObjectFromList<I> = {
[P in keyof I]: ExtractObject<I[P]>;
};
declare function f<T extends any[]>(arr: HasDuplicateKey<ExtractObjectFromList<[...T]>> extends true ? "Err" : T): any;
declare const a: C<{ name: string }, []>;
declare const b: C<{ name: string }, []>;
f([a, b])
or
declare function f<T extends any[]>(arr: [...T] extends infer P ? HasDuplicateKey<ExtractObjectFromList<P>> extends true ? "err" : P: never): any;
declare const a: C<{ name: string }, []>;
declare const b: C<{ name: string }, []>;
f([a, b])
it is not working correctly since it is losing the tuple type and it is converted to (C<{ name: string }, []>[])[]
I wonder if there is a solution to this without using as const
when passing the array, this is part of a library and I want to be backwards compactable.
So the idea is to highlight to display an error message when the keys of the first generic in C
has a collision and also ability to do some more checks on top of that
Also this is the HasDuplicateKey
type
export type HasDuplicateKey<T> = T extends readonly [infer First, ...infer Rest]
? Rest extends readonly [infer Next, ...infer Others]
? keyof First extends keyof Next
? true
: HasDuplicateKey<readonly [First, ...Others]>
: false
: false;