#Indexing a type with known keys with a variable of type string

13 messages · Page 1 of 1 (latest)

steady grotto
#

say I have a type like so

const values = ["a", "b", "c"];
type Costumer = "costumer1" | "costumer2";
type COSTUMERS: Record<Costumer, string[]> = {
  costumer1: values,
  contumer2: values,
};

and I want to write this function

function foo(key: string) {
  const values = COSTUMERS[key];
  if (values === undefined) throw "error";
  // use values as string[]
}

how do I make typescript happy? It complains with
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Record<Costumer, string[]>'.

I understand the error but I don't know how I could write this in a way that works

#

note: I can't change the signature of foo

mild stone
#

just ignore the type and validate it in code later const values = COSTUMERS[key as Costumer];

toxic goblet
honest imp
#

@steady grotto do you have control over COSTUMERS? how else is it used? the smallest change would be to use Record<string, string[]> as its type, but i don't know if that will cause problems elsewhere for you

#

also in your real code are there only two members in the Costumer union? or is it bigger? if it's only two you could explicitly check for both:

worldly marlinBOT
#
mkantor#0

Preview:```ts
...
function getCostumer(
key: string
): string[] | undefined {
if (key === "costumer1" || key === "costumer2") {
return COSTUMERS[key]
} else {
return undefined
}
}

function foo(key: string) {
const values = getCostumer(key)
if (values === undefined) throw "error"
const _: string[] = values // use values as string[]
}```

honest imp
#

(also do you mean "customer"?)

steady grotto
#

oops, yeah, COSTUMERS is a const

#

and yes, there's only two in the real code

#

but checking like that feels weird but I guess it works

#

there's just so much repetition

honest imp
#

another alternative is to widen the Record<Costumer, string[]> to Record<string, string[] | undefined> before indexing into it:

function getCostumer(key: string) {
  const stringIndexableCostumers: Record<string, string[] | undefined> = COSTUMERS;
  return stringIndexableCostumers[key];
}