1

I have the following categories of Pet:

type Pet = 'dog' | 'cat'

Then I have types for allowed DogNames and CatNames respectively:

type DogName = 'Jack' | 'Fenton' type CatName = 'Priscilla' | 'Kittykat'

I want to type the following object so that only cat names are allowed under cat and dog names are only allowed under dog, but I also don't want new pet categories to be invented unless they are in the type:


type Pet = 'dog' | 'cat'
type DogName = 'Jack' | 'Fenton'
type CatName = 'Priscilla' | 'Kittykat'

type Pets = {
   ["dog" in Pet]: {[key in DogName]: boolean}
   ["cat" in Pet]: {[key in CatName]: boolean}
}

const pets = {
   dog: {
      Jack: true
   },
   cat: {
      KittyKat: true
   }
}

The above does not work, specifically the part of "dog" in Pet

1
  • Are both dog and cat meant to be required in Pets? Commented Oct 14, 2022 at 13:30

2 Answers 2

3

Use, for the pet type, the same mapped structure you are using for the names, and get the associated names with a conditional type.

As suggested by caTS, consider changing the conditional to a lookup table for performance and maintainability in the future when there are more members of the union.

type Pet = 'dog' | 'cat'
type DogName = 'Jack' | 'Fenton'
type CatName = 'Priscilla' | 'Kittykat'

type NameFromPetType<PetType extends Pet> = PetType extends 'dog' ? DogName : CatName;
type Pets = {
   [PetType in Pet]: {[key in NameFromPetType<PetType>]?: boolean}
}

TS Playground

Sign up to request clarification or add additional context in comments.

1 Comment

Consider changing the conditional to a lookup table for performance and maintainability in the future when there are more members of the union.
1

The first thing you want to do is tell TypeScript that pets should be of type Pets. :-)

Then the pedestrian way to do this is to use Partial<Record<___, boolean>>:

type Pets = {
    dog: Partial<Record<DogName, boolean>>;
    cat: Partial<Record<CatName, boolean>>;
};

Playground link (I made the capitalization of KittyKat consistent)

Obviously, you'll need to add to Pets if you add to Pet, but that'll be the case in any solution.

Comments

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.