Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to infer Record keys based on array got as argument

Tags:

typescript

How can this be implemented with types?

const createConstants = (...keys) => {
  let record = {};
  keys.forEach(key => {
    record[key] = key;
  });
  return record;
};

like image 833
carlesba Avatar asked Nov 14 '25 17:11

carlesba


1 Answers

If you don't mind a little bit of assertion inside the function, you can do this:

const createConstants = <K extends string>(...keys: K[]): {[Key in K]: Key} => {
  let record = {} as {[Key in K]: Key};
  keys.forEach(key => {
    record[key] = key;
  });
  return record;
};

createConstants("a", "b", "c"); // { a: "a"; b: "b"; c: "c";}

A Record type is presumably not actually useful here since something like Record<Keys, Keys> is broader than the return type of the function. You can't match keys to values with a Record type.

After some further consideration, a more typesafe version of this would require that the input is of a tuple type. This will prevent false types being returned from inputs like ("a" | "b")[], which cannot be guaranteed to have either property present:

const createConstants = <K extends string>(...keys: [K, ...K[]): {[Key in K]: Key}

createConstants("a", "b", "c"); // ok

const tuple = ["a", "b", "c"] as const;
createConstants(...tuple) // ok

const undetermined = [] as ("a" | "b")[];
createConstants(...undetermined) // not ok
like image 196
lawrence-witt Avatar answered Nov 17 '25 08:11

lawrence-witt



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!