0

I have an object

const modalTypes = {
  newPizza: 'NEW_PIZZA',
  newCola: 'NEW_COLA',
  newCustom: 'NEW_CUSTOM,
}

Then I have an action creator that takes an action that is one of the modalTypes' values.

const showModal = (modalType: ModalType, body: BodyType) => {
  // do something...
}

// e.g.
showModal('NEW_PIZZA', ...)

How to get the ModalType to be NEW_PIZZA | NEW_COLA | NEW_CUSTOM?


Something similar to this, but for values.

const Foo = { a: 'FOO', b: 'BAR', c: 'BAZ' };
type Abc = keyof typeof Foo

Abc = 'a' | 'b' | 'c'
// Desired = 'FOO' | 'BAR' | 'BAZ'
2
  • Even if you could do this, I think that the types would be string rather than literals like 'NEW_PIZZA'. I think an emum may work best here if you could make that change. Commented Feb 20, 2019 at 16:46
  • 1
    why not declare an enum? Commented Feb 20, 2019 at 17:00

3 Answers 3

1

You can do it without extra assertions in 3.4 (unreleased yet, try it using npm install typescript@next) using a as const assertions, see PR.

const modalTypes = {
  newPizza: 'NEW_PIZZA',
  newCola: 'NEW_COLA',
  newCustom: 'NEW_CUSTOM',
} as const

type ModalType = typeof modalTypes[keyof typeof modalTypes]

Below 3.4, I still would not go the explicit assertion route, I would rather use a helper function to infer the correct types, it can be an IIFE:

const modalTypes = (<V extends string, T extends Record<string, V>>(o:T) => o)({
  newPizza: 'NEW_PIZZA',
  newCola: 'NEW_COLA',
  newCustom: 'NEW_CUSTOM',
})

type ModalType = typeof modalTypes[keyof typeof modalTypes]
Sign up to request clarification or add additional context in comments.

2 Comments

Wow, that first example is super sleek! Can you point to a specific change in 3.4 that allows this? Anyway, I have never thought about using IIFEs like that. Pure wizardry!
@Qwerty added a link to the PR, sorry I unusually try to add references, missed this one :) (there was even a , where I meant to add it :D)
1

As @ExplosionPills says without extra annotation the type of values is generalized, but if you are OK adding annotation this works:

const modalTypes = {
  newPizza: 'NEW_PIZZA' as 'NEW_PIZZA',
  newCola: 'NEW_COLA' as 'NEW_COLA',
  newCustom: 'NEW_CUSTOM' as 'NEW_CUSTOM',
}

type ModalType = typeof modalTypes[keyof typeof modalTypes]

Comments

1

In case when ModalType is collection of string constants you need to use Enum instead of object like this:

enum ModalType {
    newPizza = "NEW_PIZZA",
    newCola = "NEW_COLA",
    newCustom = "NEW_CUSTOM",
}
const showModal = (modalType: ModalType[keyof ModalType]) => {
    // do something...
};
showModal("NEW_PIZZA");

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.