Home > Enterprise >  Typescript compilation issues
Typescript compilation issues

Time:01-18

I have a complex interface. A simpler version of it would be something like this

Interface Person {
'name': string, 'address': string, 'age': number, 'height': number 
}

const person:Person = {'name': 'Yair', 'address': 'here', 'age': 12, 'height': 186}

Now say I wanted to create a function to dynamically update the name or address. This works well:


let updateNameOrAddress = (key: "name"|"address", value: string): void => {
    person[key] = value
}

However, defining keys this way will get hard when I'll add more and more string fields. So I try something like this:

let updateNameOrAddress = (key: keyof Person, value: string): void => {
    person[key] = value
}

Well, this creates this error: Type 'string' is not assignable to type 'never' I have reasons to believe that this is because name can now also be "age" or "height". I'd stick to adding types as possibilities for "name" - but my real object has lots of values. Is there a way to get keyof, to retrive only the string / numberic keys?

Thanks in advance

CodePudding user response:

Using generics you can check the changed key and map it onto Person to retrieve the property's value type generically.

Notice that T is accessing Person[T], this means that the type of the value parameter can be determined based on the given key argument.

interface Person {
  'name': string, 'address': string, 'age': number, 'height': number
}

const person: Person = { 'name': 'Yair', 'address': 'here', 'age': 12, 'height': 186 }

const updateNameOrAddress = <T extends keyof Person>(key: T, value: Person[T]): void => {
  person[key] = value;
}

updateNameOrAddress("name", "John"); // Ok
updateNameOrAddress("age", "47"); // Error!
updateNameOrAddress("age", 47); // Ok

Playground

CodePudding user response:

Is there a way to get keyof, to retrive only the string / numberic keys?

interface Person {
  'name': string;
  'address': string;
  'age': number;
  'height': number;
}

type KeysOfType<T, U> = {
  [K in keyof T]: T[K] extends U ? K : never
}[keyof T];

const person: Person = { 'name': 'Yair', 'address': 'here', 'age': 12, 'height': 186 }

let updateNameOrAddress = (key: KeysOfType<Person, string>, value: string): void => {
  person[key] = value
}

TS Playground

  • Related