2

I have the key-value-pair object in the following example


interface ItemType {
    a: number;
    b: string;
}

const list = {
    first: {a: 1, b: 'one'},
    second: {a: 2, b: 'two'},
    third: {a: 3, b: 'three'},
} as { [key in keyof typeof list]: ItemType }

But it raises an error such as TS2313: Type parameter 'key' has a circular constraint..

I want all items to be of type of ItemType, but still want the list to save keys that I have inserted. If I cast it to { [key in string]: ItemType }, I will loose key names of the list. :(

1 Answer 1

8

In cases where you want to verify that a value is assignable to a type without widening it to that type and possibly throwing away information you care about, you can use a helper identity function, like this:

const itemDict = <K extends PropertyKey>(dict: { [P in K]: ItemType }) => dict;

Here itemDict() should only accept as an argument an object of the type you're looking for: whose keys are anything key-like K extends PropertyKey which will be inferred by the compiler when you call it, and whose properties are ItemTypes. Because the set of keys, K, is part of the type, it will not be forgotten:

const list = itemDict({
  first: { a: 1, b: 'one' },
  second: { a: 2, b: 'two' },
  third: { a: 3, b: 'three' },
});

list.second.a.toFixed(); // okay

list.fourth; // error!
// Property 'fourth' does not exist on type 
// '{ first: ItemType; second: ItemType; third: ItemType; }'

Notice that list is inferred by the compiler to be type {first: ItemType, second: ItemType, third: ItemType}, as desired.

Playground link to code

Sign up to request clarification or add additional context in comments.

1 Comment

I wanted this for writing a library for react-static-router with TypeScript, npmjs.com/package/react-static-routing

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.