Home > Software design >  Typescript: Can I use prop foo string union to define prop bar map w/foo strings as keys?
Typescript: Can I use prop foo string union to define prop bar map w/foo strings as keys?

Time:07-25

Wasn't sure how to word this.

type FooType = Record<string, number>;
type BarType = Record<string, string>;

type PossibleTypes = "Foo" | "Bar";

type TypeMap = {
  Foo: FooType;
  Bar: BarType;
}

type FProps<?> = {
  type: PossibleTypes
  data: TypeMap[?]
}

function F ({ type, data }: FProps<?>) {
  return { type, data }; 
}

const {type, data} = F({ type: "Foo", data: { Foo: 42 } });

data.Foo = "Baz" //type error

I want to ensure the last line would throw a type error without having to explicitly type data. Is there a way to do this so that the value of the param type is used to defined the type of the data param?

I tried some generics, but I either was not doing it correctly or was going down the wrong path. In the above code I had tried FProps<PossibleTypes> then type FProps<T> and data: TypeMap[T] with error TS2536: Type 'T' cannot be used to index type.

CodePudding user response:

First, let's modify FProps so that it takes "Foo" | "Bar" as the generic type.

type FProps<T extends PossibleTypes> = {
  type: T
  data: TypeMap[T]
}

We also need to add a generic type to the function F which holds the type of the type property of the passed object.

function F<T extends PossibleTypes>({ type, data }: FProps<T>) {
  return { type, data }; 
}

Now we get an appropriate error.

const { type, data } = F({ type: "Foo", data: { Foo: 42 } });

data.Foo = "Baz" // Error: Type 'string' is not assignable to type 'number'.

Playground

  • Related