0

I have the following example that I'd like to make it work. See comments in code:

const cars = {
    "audi": {
        manufacturer: "audi",
        colors: ["red", "blue"]
    },
    "mercedes": {
        manufacturer: "mercedes",
        colors: ["blue", "black"]
    }
} as const

type CarType = typeof cars[keyof typeof cars]

type Mapper<C extends CarType> = {
    manufacturer: C["manufacturer"]
    color: C["colors"][number]
}

type Car = Mapper<CarType>

const car: Car = {
    manufacturer: "audi",
    color: "black" // <- this is wrong, only "red" and "blue" are valid
}

As it can be seen from the example, I would like to have a color field that has only a single option and is derived from the list of valid colors.

The issue is that my Mapper type is wrong, because it does not pick out individual CarTypes, but I don't know how to write it.

1 Answer 1

3

A stand-alone type that achieves this would look like this:

type Car = {
  [K in keyof typeof cars]: {
    manufacturer: typeof cars[K]["manufacturer"],
    colors: typeof cars[K]["colors"][number]
  }
}[keyof typeof cars]

You can map over the cars to create a valid object for each key of cars. With [keyof typeof cars] we can index this type to get a union of all possible car types.

Playground


A more generic solution:

type Mapper<T extends Record<string, { manufacturer: string, colors: readonly string[] }>> = {
  [K in keyof T]: {
    manufacturer: T[K]["manufacturer"],
    colors: T[K]["colors"][number]
  }
}[keyof T]

const car: Mapper<typeof cars> = {
    manufacturer: "audi",
    color: "black" // <- this is wrong, only "red" and "blue" are valid
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, looks great. Will test it later and accept it soon.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.