Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Typescript Have the type of the property from an object

I am trying to do a generic react form reducer. For that "Value" must have the type of T by "name". Im not sure to be comprehensive so here is an example that will be clearer:

Example:

type RandomObject = { test1: number, test2: string, test3: string[] }

type ActionChangeInput<T> = {
  name: keyof T
  value: typeof T["name"] // Get type of name
}

I want value to be a number because value of name is "test1" and "test1" type is number.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

const a: ActionChangeInput<RandomObject> = {
  name: "test1", // type is "test1" | "test2" | "test3"
  value: 12931 // Expect number here
}

Sorry if it’s not clear but it’s hard to explain something I don’t understand (that’s why im here).

>Solution :

What you want is for ActionChangeInput<T> to resolve to a union of all possibilities. You can do that with a mapped type that maps over each property of T and creates type that pairs name and value types for just that property.

Something like:

type ActionChangeInput<T> = {
  [K in keyof T]: {
    name: K
    value: T[K]
  }
}[keyof T]

This maps over each property in T with [K in keyof T], and creates an object type for each combination of name as K and value as T[K].

You then index that resulting object by it’s own keys to get a union of its values.

With the RandomObject type, that should resolve to:

type RandomObject = { test1: number, test2: string, test3: string[] }

type Test = ActionChangeInput<RandomObject>
/*
| { name: 'test1', value: number }
| { name: 'test2', value: string }
| { name: 'test3', value: string[] }
*/

So any valid value of that type must have a name and value type that match in that list of unions.

The rest now behaves as you would expect:

type RandomObject = { test1: number, test2: string, test3: string[] }

// fine
const a: ActionChangeInput<RandomObject> = {
  name: "test1",
  value: 12931,
}

// error
const b: ActionChangeInput<RandomObject> = {
  name: "test2",
  value: 12931, // Type 'number' is not assignable to type 'string'.(2322)
}

See Playground

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading