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

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.