0

Is this possible to do:

type Dessert = 'cake' | 'chocolate' | 'cookie'

const arrWithAllDessertTypes  = ['cake', 'chocolate'] // Want TS to complain that it does contain `cookie`

I have googled and searched SO for an answer but it always talks about doing as:

const desserts = ['cake' , 'chocolate' , 'cookie']

But I'm getting my Dessert type from an end-point response.

5
  • 1
    Can you clarify what you mean by "I getting my Dessert type from an end-point response"? TypeScript is compile-time not run-time, so I'm not sure how you could dynamically be retrieving a type from an API at run-time and have it do anything useful Commented Feb 3, 2023 at 9:20
  • I'm not retrieving the type dynamically. They are being typed/generated. So if the end-point decides to include muffin to Dessert then I'll get a updated type file for this change. But I have some test that uses these types and I would then like to have TS complain that I do not test muffin Commented Feb 3, 2023 at 9:37
  • It's a bit unclear, you want TypeScript to give an error if you try to enter something that does not belong to the Desert type? Also, you never did specify the array type for the arrWithAllDessertTypes variable. Try const arrWithAllDessertTypes: Dessert[] = ['cake', 'chocolate', 'water'] Commented Feb 3, 2023 at 9:40
  • Yes, I want it to error out if I enter something that is not a Dessert (water) AND if it is missing an dessert. It is intentional that I haven't specified the array type - this is what the question is about. How do specify a more strict type than : Dessert[] or as Dessert[] or satisfies Dessert[]? Commented Feb 3, 2023 at 9:50
  • Does this answer your question? String Union to string Array --Hmm, the type is autogenerated though. So not sure if you can make it work Commented Feb 3, 2023 at 10:31

2 Answers 2

2

You can do this by using a const assertion

    const MyDessert = ['cake', 'chocolate', 'cookie'] as const;
    type Dessert = typeof MyDessert[number];  // "cake" | "chocolate" | "cookie" this defines the type you have on your first line

You can play with it in this TS playground

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

4 Comments

Since DesertT will rarely be useful, you can also use type Dessert = typeof Dessert[number];
Yeah, completely correct, just added it to cover the readonly bit :)
this is going the wrong way :-) - This goes from an array to type but I want to go the other way around: From a type to a "strict" array.
I don't think we can create an array from the type because we cannot assemble an array at runtime if types don't exist at runtime. But we can do the inverse which is what this is
0

I wrote my example with Dessert to make it generic. I did not find the exact solution, but found a way that will make TS tell me check my test files when some of the types are updated:

    import { IsEqual } from 'type-fest'


    const negativeStatusCases = ['pending', 'failed', 'cancelled', 'expired', 'in_progress'] as const
    negativeStatusCases.forEach((negativeStatus) => {
      describe(negativeStatus, () => {
        it('shows message with variant of "warning"', async () => {
          ...
        })
      })
    })

    it('covers all non `succeeded` status cases', () => {
      type Status = Awaited<ReturnType<typeof api.fetchPaymentStatus>>['status']
      type NegativeStatus = Exclude<Status, 'succeeded'>
      const allStatusCasesAreCovered: IsEqual<NegativeStatus, (typeof negativeStatusCases)[number]> = true
      expect(allStatusCasesAreCovered).toBe(true)
    })

hope it helps others 🙂

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.