1

I have code like this :

interface Entity{
    value : number | string;
}
interface Abc{
    entity: Entity;
    entityValues : number[] | string[] // <----- I want to change this type
}

Even when I have an entity object of type number, entity values can be string[] or number[]. Since already have entity set, I want entityValues also to be dynamically determined.

Vamshi
  • 9,194
  • 4
  • 38
  • 54
  • 1
    So you want `type Abc = {entity: {value: number}; entityValues: number[]} | {entity: {value: string}; entityValues: string[]}`? – jcalz Feb 22 '19 at 20:09
  • And if not, please flesh out your question to explain your use case. – jcalz Feb 22 '19 at 20:19
  • That should work , let me give it a try . If I have more types for entity, it gets too verbose. I thought there would be a simpler option. – Vamshi Feb 22 '19 at 21:30

1 Answers1

1

It looks like what you want is a way to make the entityValues field a :

// Distribute the types of a union across arrays
// This gets us `string[] | number[]` instead of `(string | number)[]`
// If you want to store the values of _all_ the fields, instead of fields of a single type
// simply use `Entity[EntityFields][]` for `entityValues`
// See https://stackoverflow.com/a/53996824/135978 for more information
type HomogenousArray<T> = T extends unknown ? T[] : never;

interface Abc<Entity, EntityFields extends keyof Entity = keyof Entity> {
  entity: Entity,
  // Values of a particularly typed sub-section of your entity's fields
  entityValues: HomogenousArray<Entity[EntityFields]>
  // Values of any or all of your entity's fields
  anyEntityValues: Entity[EntityFields][]
}

Usage is very straightforward:

interface Entity {
  id: number,
  value: string
}

type Z = Abc<Entity>;

const z: Z = {
  entity: {id: 1, value: "hi"},
  entityValues: [1, 2, 3],
                // ["strings", ""] will also work
                // ["strings", 123] will *not* work
  anyEntityValues: [1, "mixed types", 2, "work here"] 

};

See also: https://stackoverflow.com/a/53996824/135978

Sean Vieira
  • 155,703
  • 32
  • 311
  • 293