1

I already know that that keyof TCreate produces literal union of its keys in the type TCreate. But I’m confused about what TCreate[keyof TCreate] represents.

Why do we write it this way?

How does it work in TypeScript?

Why does it produce a union of all possible value types, instead of preserving the mapping between a specific key and its corresponding value type? For example, given this type:

type TCreate = {
  id: number;
  name: string;
  active: boolean;
};

keyof TCreate gives "id" | "name" | "active"

TCreate[keyof TCreate] gives number | string | boolean.

I think I expected it to somehow keep the relationship like

["id", number] | ["name", string] | ["active", boolean]

instead of collapsing everything into a union.

Could someone explain why it works this way??

2
  • Please edit this question so it's clearly asking a single well-defined question. Right now you're talking about Object.entries() in the title, but your question has little to do with it. The TypeScript typings for Object.entries() does not produce anything with keyof in it, and if you want it to, you wouldn't write the type you're talking about. Currently the question is confusing and risks being closed as needing clarification. Commented Sep 20 at 22:21
  • I've updated my answer to demonstrate how you could get the type that you expected to get. Commented Sep 21 at 18:13

1 Answer 1

3

I’m confused about what TCreate[keyof TCreate] represents.

Why do we write it this way?

How does it work in TypeScript?

The type syntax A[B] is called an "indexed access type". It pulls out the property type(s) of A corresponding to the key(s) B. For example:

type A = { key1: string; key2: number; key3: boolean }
type Example = A['key1']
//   ^? - type Example = string

This works when the key is a union type as well. For example:

type A = { key1: string; key2: number; key3: boolean }
type Example = A['key1' | 'key2']
//   ^? - type Example = string | number

You already know that keyof A gets a union type representing all the keys of A. Combining that with what I've explained above, A[keyof A] will resolve to a union of all the property value types of A. For example:

type A = { key1: string; key2: number; key3: boolean }
type Example = A[keyof A]
//   ^? - type Example = string | number | boolean

In the above example, keyof A is 'key1' | 'key2' | 'key3', so A[keyof A] is the same as A['key1' | 'key2' | 'key3'].


I think I expected it to somehow keep the relationship like

["id", number] | ["name", string] | ["active", boolean]

A type like that could be derived by mapping over the properties of the initial type. For example:

type A = { key1: string; key2: number; key3: boolean }
type Example = { [K in keyof A]: [K, A[K]] }[keyof A]
//   ^? - type Example = ["key1", string] | ["key2", number] | ["key3", boolean]
Sign up to request clarification or add additional context in comments.

1 Comment

Make sense now. Thank you

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.