Home > Enterprise >  How to make a Record in TypeScript can accept different types
How to make a Record in TypeScript can accept different types

Time:07-23

I want to ask about Record in TypeScript, currently when I use Record as parameter type in a function then I get error in my code because it can't accept different type.

type Keys = 'name' | 'qty';

const getValueByKey = <T = any>(items: Record<Keys, T>, key: Keys) => {
  return items[key];
}
getValueByKey({ name: 'fulan', qty: 1}, 'name'); // Error: Type 'number' is not assignable to type 'string'.(2322)

TypeScript Playground

The goal is actually to get the type of the value in the function.

How can I make a Record accept values of different types? Thank you

CodePudding user response:

It seems like what you want to do is to accept an object type that has the keys in your union, and return a value from the object based on the key parameter while also inferring what constitutes a valid key parameter from the object that is provided. This type of inference is possible using generic constraints.

Keep in mind that TypeScript is structurally typed, so any object that has the keys name and qty will be allowed (even if it has additional keys), and you'll be able to use any key from that object for the key argument.

TS Playground

type Key = 'name' | 'qty';

function getValueByKey <
  T extends Record<Key, any>,
  K extends keyof T,
>(items: T, key: K): T[K] {
  return items[key];
}

const obj = {name: 'fulan', qty: 1};

const value1 = getValueByKey(obj, 'name');
    //^? const value1: string

const value2 = getValueByKey(obj, 'qty');
    //^? const value2: number


and if you try to use a key that's not in the object, TS will (appropriately) emit a compiler diagnostic error:

const value3 = getValueByKey(obj, 'not_a_key');
//                                ~~~~~~~~~~~
// Argument of type '"not_a_key"' is not assignable to parameter of type '"name" | "qty"'. (2345)

  • Related