2

I'm looking to generate a type from an Object's keys, and values of arrays of strings. The type needs to represent all the possible strings, i.e.

const Actions = {
  foo: ['bar', 'baz'],
}

# type generated from Actions to equal:
type ActionsType = 'foo' | 'bar' | 'baz'

I need to retain Actions as it's to be passed to a method, therefore:

const Actions = {
  foo: ['bar', 'baz'],
} as const


type ActionsType = keyof typeof Actions | typeof Actions[keyof typeof Actions][number]

whilst generating the type correctly didn't allow me to pass Actions to a method expecting Record<string, string[]> as the keys and values became readonly.

How can I generate the required type whilst still being able to use Actions as a non-readonly Object?

3
  • What you have done will work, but you need to use a const assertion on your array.. eg.. foo: ['bar', 'baz'] as const, otherwise typescript will see the array as been dynamic. Commented Nov 13, 2020 at 10:16
  • @Keith, unfortunately, the method the object is passed to expects a mutable string[] therefore setting as const on the object, or the individual arrays generates the following error: "The type 'readonly ["bar", "baz"]' is 'readonly' and cannot be assigned to the mutable type 'string[]'" Commented Nov 13, 2020 at 10:26
  • Seems like you can use the "older" approach to generate types based on an array by using a function helper: playground. source Commented Nov 16, 2020 at 9:35

1 Answer 1

4
+50

Here is a simple solution to revert readonlyness of const assertions / as const:

type Mutable<T> = {-readonly [K in keyof T]: Mutable<T[K]>}
The following will compile with a type assertion and adequate type safety:
type T1 = Mutable<typeof Actions> // { foo: ["bar", "baz"]; }

function foo(a: Record<string, string[]>) {}
foo(Actions as Mutable<typeof Actions>) // works

Be aware, that Actions object might be mutated inside foo, so you better treat it as mutable in the containing module as well. A cleaner alternative would be to change foo signature to receive readonly arrays:

function foo2(a: Record<string, readonly string[]>) {}
foo2(Actions) // works without type assertion

Code demo

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

1 Comment

thanks for your help with this. It led to a follow on question, which if you could provide any help on would be awesome: stackoverflow.com/questions/64876213/…

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.