1

It's easier to illustrate with code than to explain with words:


// `type` or `interface` doesn't matter to me.
interface MyCollection {
  name: string;
  age: number;
}

// The best and simplest solution I came up with.
type List<T> = Array<{ key: keyof T}>;

// I want `MyCollection` _keys_ to be present 
// as _values_ for `itemkey` prop in `myList` items.
const myList: List<MyCollection > = [
  {  itemkey: 'name' },
  {  itemkey: 'age' },
]

It's already not bad, because intellisense works and prevents from using wrong keys. But I need to guarantee that every key present in MyCollection is present in myList, i.e. current solution allows this:

const myList: List<MyCollection > = [
  {  itemkey: 'age' },
]

BONUS: would be the possibility to match MyCollection key type as well, e.g.:

type List<T> = Array<{ key: keyof T, value: T[keyof T] }>;

// !BAD `value` accepts either `number` or `string`, 
// but should only allow `number`.
const myList: List<MyCollection> = [
  {  key: 'age', value: 'should be number, not string' },
]

As far as I know there's no possibility to iterate an interface entries to do this.

What I tried is in the description of the problem. I explored mapped types, tuples, remapping via as and whatever else I could find on the web and in the docs.

Honestly, it's very confusing, a good old JS iteration declaring some kind of static constrains would be way more simpler :D

Mycolaos
  • 74
  • 1
  • 5
  • You could create a type that generates all the possible permutations... but this wouldn't work for larger interfaces (5 keys is already 120 possibilities). Then you would need a helper function to do the inferencing and validate the given type... – kelsny Nov 20 '22 at 19:29
  • I'd say you're looking for an "exhaustive array type" which TS doesn't directly support. Various approaches are listed in the answers to the linked questions. – jcalz Nov 20 '22 at 19:43

0 Answers0