How to make Typescript infer the keys of an object but define type of its value?

So you want something that infers keys but restricts the value types and uses excess property checking to disallow extra properties. I think the easiest way to get that behavior is to introduce a helper function:

// Let's give a name to this type
interface ElementType {
  nodes: number,
  symmetric?: boolean
}

// helper function which infers keys and restricts values to ElementType
const asElementTypes = <T>(et: { [K in keyof T]: ElementType }) => et;

This helper function infers the type T from the mapped type of et. Now you can use it like this:

const elementsTyped = asElementTypes({
  square: { nodes: 4, symmetric: true },
  triangle: { nodes: 3 },
  line: { nodes: 2, notSymmetric: false /* error where you want it */} 
});

The type of the resulting elementsTyped will (once you fix the error) have inferred keys square, triangle, and line, with values ElementType.

Hope that works for you. Good luck!

Leave a Comment