2

I'm importing a .json file, and i want to get all the keys as optional parameters

import jsonFile from '../public/sample.json'

The json has unknown keys but, for the question, let's say it has the following:

{
  "greetings": {
    "hello": "Hello",
        "hello_informal": "Hi",
        "good_morning": "Good morning",
        "good_afternoon": "Good afternoon",
        "good_night": "Good night",
        "bye": "Bye"
  },
  "commons": {
    "pagination": {
            "first_page": "First page",
            "last_page": "Last page",
            "next_page": "Next page",
            "previous_page": "Previous page"
        }
  },
  "home": "Home sweet home"
}

And i have a function with 1 parameter.

function sample(keyValue: TypeKeyValue) {
  // logic here...
  console.log("Thank you Stackoverflow", keyValue)
}

My question is how create a type for that keyValue param for all the object keys (nested keys included, prefixed by parent keys with a dot). Value of the keys should not matter, just collect all the keys as optional.

i was trying this but is not working as expected:

type TypeKeyValue: keyof jsonFile 

The desired result should be an automated way to get the following:

type TypeKeyValue: "greetings" | "greetings.hello" | "greetings.hello_informal" | "greetings.good_morning" | "greetings.good_afternoon" | "greetings.good_night" | "greetings | bye" | "commons" | "commons.pagination" | "commons.pagination.first_page" | "commons.pagination.last_page" | "commons.pagination.next_page" | "commons.pagination.previous_page" | "home"

Any help or solution would be much appreciated

Héctor León
  • 2,210
  • 2
  • 23
  • 36

2 Answers2

3

As long as you have the following options in your tsconfig.json typescript should automatically detect the type of imported JSON files:

"resolveJsonModule": true,
"esModuleInterop": true,

Afterwards you can get all keys of a JSON object in a type like this:

import jsonFile from '../public/sample.json'

type TypeKeyValue = keyof typeof jsonFile 

If you also want all nested paths you will need to do something like this:

type Join<K, P> = K extends string | number ?
    P extends string | number ?
    `${K}${"" extends P ? "" : "."}${P}`
    : never : never;


type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
    11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...0[]]

type Paths<T, D extends number = 10> = [D] extends [never] ? never : T extends object ?
    { [K in keyof T]-?: K extends string | number ?
        `${K}` | Join<K, Paths<T[K], Prev[D]>>
        : never
    }[keyof T] : ""

type Leaves<T, D extends number = 10> = [D] extends [never] ? never : T extends object ?
    { [K in keyof T]-?: Join<K, Leaves<T[K], Prev[D]>> }[keyof T] : "";

type Nested = Paths<typeof json>

In this case Nested will have all paths of the object.

Tobias S.
  • 21,159
  • 4
  • 27
  • 45
0

For a start you could use

type TypeKeyValue: keyof typeof jsonFile;

which will give you the root level keys.

Flo Ragossnig
  • 1,341
  • 14
  • 38
  • Thank you Flo, this will help for someone looking to get just the root as you said and is a super clean solution. but i was asking for the nested levels too. – Héctor León Apr 18 '22 at 20:20