Home > Blockchain >  In TypeScript, how do I create a number union from an array within a Record
In TypeScript, how do I create a number union from an array within a Record

Time:02-26

In TypeScript, I have a Record like this:

const entityTypeExemptPayeeCodeMap: Record<EntityType, readonly PayeeCode[]> = {
  [EntityType.Smllc]: [1, 2, 3, 4, 6, 7, 11, 12],
  [EntityType.Llc]: [1, 2, 3, 4, 6, 7, 11, 12],
  [EntityType.CCorp]: [1, 2, 3, 4, 5, 6, 7, 9, 11, 12],
  [EntityType.SCorp]: [1, 2, 3, 4, 5, 6, 7, 9, 11, 12],
  [EntityType.Partnership]: [1, 2, 3, 4, 6, 7, 11, 12],
  [EntityType.TrustEstate]: [1, 2, 3, 4, 6, 7, 8, 10, 11, 12, 13],
  [EntityType.Other]: [1, 2, 3, 4, 6, 7, 8, 10, 11, 12, 13],
} as const;

I'd like to get a number union type from one of the arrays inside the Record. I thought this may work:

type SmllcExemptPayeeCodes = typeof entityTypeExemptPayeeCodeMap[EntityType.Smllc]

But that just gives me a type of readonly PayeeCode[] and not a union of the values in the array.

If I make entityTypeExemptPayeeCodeMap not be a Record, like this:

const entityTypeExemptPayeeCodeMap = {
  [EntityType.Smllc]: [1, 2, 3, 4, 6, 7, 11, 12],
  [EntityType.Llc]: [1, 2, 3, 4, 6, 7, 11, 12],
  [EntityType.CCorp]: [1, 2, 3, 4, 5, 6, 7, 9, 11, 12],
  [EntityType.SCorp]: [1, 2, 3, 4, 5, 6, 7, 9, 11, 12],
  [EntityType.Partnership]: [1, 2, 3, 4, 6, 7, 11, 12],
  [EntityType.TrustEstate]: [1, 2, 3, 4, 6, 7, 8, 10, 11, 12, 13],
  [EntityType.Other]: [1, 2, 3, 4, 6, 7, 8, 10, 11, 12, 13],
} as const;

then SmllcExemptPayeeCodes becomes a union as I would expect. Is there any way to keep the Record type for entityTypeExemptPayeeCodeMap and still retrieve a union?

In the above examples, EntityType is:

enum EntityType {
  Smllc = "smllc",
  Llc = "llc",
  CCorp = "cCorp",
  SCorp = "sCorp",
  Partnership = "partnership",
  TrustEstate = "trustEstate",
  Other = "other",
}

PayeeCode is:

type PayeeCode = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13;

CodePudding user response:

I thought this may work:

type SmllcExemptPayeeCodes = typeof entityTypeExemptPayeeCodeMap[EntityType.Smllc]

...

If I make entityTypeExemptPayeeCodeMap not be a Record, like this:...then SmllcExemptPayeeCodes becomes a union as I would expect.

That's odd, I'd expect you to need [number] on that.

Is there any way to keep the Record type for entityTypeExemptPayeeCodeMap and still retrieve a union?

I don't think so, TypeScript will defer to what you've told it; but you can use an intermediate variable (codeMap in this example):

const codeMap = {
    [EntityType.Smllc]: [1, 2, 3, 4, 6, 7, 11, 12],
    [EntityType.Llc]: [1, 2, 3, 4, 6, 7, 11, 12],
    [EntityType.CCorp]: [1, 2, 3, 4, 5, 6, 7, 9, 11, 12],
    [EntityType.SCorp]: [1, 2, 3, 4, 5, 6, 7, 9, 11, 12],
    [EntityType.Partnership]: [1, 2, 3, 4, 6, 7, 11, 12],
    [EntityType.TrustEstate]: [1, 2, 3, 4, 6, 7, 8, 10, 11, 12, 13],
    [EntityType.Other]: [1, 2, 3, 4, 6, 7, 8, 10, 11, 12, 13],
} as const;
const entityTypeExemptPayeeCodeMap: Record<EntityType, readonly PayeeCode[]> = codeMap;

type SmllcExemptPayeeCodes = (typeof codeMap)[EntityType.Smllc][number];
//   ^? type SmllcExemptPayeeCodes = 1 | 2 | 3 | 4 | 6 | 7 | 11 | 12

Playground link

Then if you want things to only use the Record version, only expose entityTypeExemptPayeeCodeMap to other code and not codeMap.

  • Related