John Smith
John Smith

Reputation: 4363

Assert that for every value of a const array, an object has a key

const supported = ["a", "b", "c"];
const someObject = {a: 2, b: 3}; // I want TS to throw: error, has no 'c'!

I've got a const array of strings. How do I assert that an object's keys cover all the values?

Upvotes: 1

Views: 709

Answers (1)

zerkms
zerkms

Reputation: 255025

You could do

const supported = ["a", "b", "c"] as const;

const someObject: Record<typeof supported[number], number> = {a: 2, b: 3};

It enforces all values to be numbers and the object to have all the keys from supported.

You surely can relax the type of the values to be unknown or any.

If you for some reason don't want to use the built-in Record<K, V> type you can always expand it to { [P in typeof supported[number]]: number }.

Important note: the supported value must be known compile time.

Playground: https://www.typescriptlang.org/play?ssl=1&ssc=38&pln=1&pc=43#code/MYewdgzgLgBBCuAHRIBOUCmATGBeGA2gEQCGRANDEQEYVXBEC6MJEMokUA3ALABQ-DtDggAthgDy1AFYZgUAFwwASnLRYAPFACeiDCABmcJCnTYCYeKOoZUjSpeu2AfHhgBvEkoBMlakoBmAF8uGAB6MJgASRgAdxIwWAAVAGUYKBB0gAtUEFilW1zUSizWGDBMgHJgSoBCIA

Update:

a solution to have some keys optional:

const supported = ["a", "b", "c", "d", "e"] as const;

type Keys = typeof supported[number];
type OptionalKeys = "d" | "e";
type MandatoryKeys = Exclude<Keys, OptionalKeys>

const someObject: Record<MandatoryKeys, number> & Partial<Record<OptionalKeys, number>>  = {a: 2, b: 3, c: 42};

https://www.typescriptlang.org/play?#code/MYewdgzgLgBBCuAHRIBOUCmATGBeGA2gEQCGRANDEQEYVXB1FaMZEC6MJEMokUA3AFgAUCKgBPRBhgBpDOO74JUkADM4SFOmwEw8ALbUMqNkOHLpAeURQAluBIAbOQrxVmMAD5VWZizABZEjAsEig0cRdFGABRAA9gR3gsDAAeKMprOwdneQgAPhERXmg4EH0MS2oAKwxgKAAuGAAlOrQsVKCQsIiMmD1DY3yYADIYAAUSdFsnVNbQVA6s+zAnPoGjVHzhtwBvEiaAJkpqJoBmSmAmgBZDgF9+IA

Upvotes: 3

Related Questions