david_adler
david_adler

Reputation: 10912

Value must be keyof keys in object

Would like to enforce that values point to key of type like so, not sure how best to do it

type Graph = {
  [nodeId: number]: Array<keyof Graph>
}

const graph: Graph = {
  0: [1, 2, 3],
  1: [2],
  2: [3],
  3: [1],
}

Also tried

type Graph = {
  [nodeId: number]: Array<nodeId>
}

no luck

Upvotes: 0

Views: 178

Answers (1)

jcalz
jcalz

Reputation: 327934

TypeScript can't really represent Graph as a concrete type. However, it is possible to represent it as a generic type where the numeric keys K are part of the type:

type Graph<K extends number> = { [P in K]: K[] };

And then you can use a helper function to infer the proper K value for a given value:

const asGraph = <K extends number, V extends K>(g: Record<K, V[]>): Graph<K> =>
  g;

const goodGraph = asGraph({
  0: [1, 2, 3],
  1: [2],
  2: [3],
  3: [1]
}); // Graph<0 | 1 | 2 | 3>

And it correctly rejects bad graphs:

const badKey = asGraph({
  zero: [1], // error! "zero" does not exist in Record<number, number[]>
  1: [1]
});

const badValue = asGraph({
  0: [1],
  1: [0],
  2: [8675309], // error! number not assignable to '0 | 1 | 2'.
  3: ["zero"] // error! string also not assignable to '0 | 1 | 2'
});

Hope that helps. Good luck!

Link to code

Upvotes: 1

Related Questions