You can do such a check like so
const arr = check([
[a, ["propA"]],
[b, ["propB"]],
[a, ["propB"]], // Type '"propB"' is not assignable to type '"propA"'
[a, ["propC"]], // Type '"propC"' is not assignable to type '"propA"'
[b, ["propA"]], // Type '"propA"' is not assignable to type '"propB"'
[b, ["propD"]] // Type '"propD"' is not assignable to type '"propB"'
]);
type Entry = readonly [unknown, readonly string[]];
type Check<T extends readonly Entry[]> = {
[K in keyof T]: Related<T[K]>
};
type Related<T extends Entry> =
T extends readonly [infer A, unknown]
? [A, (keyof A)[]]
: never
const check = <const T extends readonly Entry[] & Check<T>>(x: T) => x
playground
If you need the inferred type to be mutable, consider doing
type Check<T extends readonly Entry[]> = {
-readonly [K in keyof T]: Related<T[K]>
// ----------
};
I realise the question was a little ambiguous, which explains novarx's answer, because there is a syntax error. You could be willing to write
const arr = check([
a, ["propA"],
b, ["propB"],
a, ["propB"], // Type '"propB"' is not assignable to type '"propA"'
a, ["propC"], // Type '"propC"' is not assignable to type '"propA"'
b, ["propA"], // Type '"propA"' is not assignable to type '"propB"'
b, ["propD"] // Type '"propD"' is not assignable to type '"propB"'
]);
This is also possible to check, but you need to prevent TS from widening the inferred type in different spots so you can work with it:
type Entries = readonly (unknown | string[])[];
type Narrow<T> = { [K in keyof T]: T[K] extends Function ? T[K] : Narrow<T[K]> };
type Check<T> =
T extends readonly [infer A, infer _, ...infer Rest]
? [A, (keyof A)[], ...Check<Rest>]
: T
const check = <T extends Entries>(x: Check<Narrow<T>>) => x
playground
This version is not as clean as the first one. There is nothing stopping you from writing check([a, ["propA"], b, ["propB"], ['propC']]) because we need to infer the first element of each pair as unknown and we can't enforce that we are dealing with pairs. However, as soon as you add another object after 'propC', the type checker warns you that there is a problem although it's can't quite pinpoint the cause of the problem.