Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Import JSON file as const in TypeScript

I would like to create a union type from a property of the elements of an array. If the array were inline, that would be pretty straightforward using a constant assertion.

const arr = [{ "name": "One" }, { "name": "Two" }] as const;

type name = typeof arr[number]["name"];
// name = "One" | "Two"

Note that without as const the type name becomes equal to string, which is not the intent.

The problem I'm facing is that the array is defined in a separate JSON file. I set "resolveJsonModule": true in the TypeScript options so I can import the JSON file in my module. But then the compiler widens the type of all properties in the array as there is no as const on the definition.

import * as arr from "./array.json";

type name = typeof arr[number]["name"];
// name = string (!)

Is there a way I can import a JSON file without type widening?

like image 874
Leonor Avatar asked Feb 18 '20 12:02

Leonor


People also ask

Can you use json in TypeScript?

Introduction to TypeScript JSON type. The TypeScript comes up with the functionality of working with JSON Type data. JSON being the JavaScript Object Notation, is used to make a data model that is easy to write and read. We can easily analyze large and complex data set with this TypeScript JSON type.

Where do you put resolveJsonModule?

Make sure to add these settings in the compilerOptions section of your tsconfig. json (documentation): You need to add --resolveJsonModule and --esModuleInterop behind tsc command to compile your TypeScript file.


1 Answers

I needed an answer to this too, and then realized, "Hey, that wouldn't be a hard npm package to write."

I don't believe there is a pure TS way to do this. The package I created is called ts-json-as-const.

npm install -D ts-json-as-const
npx ts-json-as-const ./path/to/file.json ./path/to/second/file.json
Example JSON file (example.json)
{
  "foo": {
    "bar": false,
    "baz": true,
    "i-can": "hascheezburger"
  },
  "array": [ 1, 2, 3, { "foo": 1, "bar": [ 4, 5 ] }, 6 ]
}
Output example.json.d.ts
interface Example {
  foo: {
    bar: false;
    baz: true;
    'i-can': 'hascheezburger';
  },
  array: [
    1,
    2,
    3,
    {
      foo: 1;
      bar: [
        4,
        5
      ]
    },
    6
  ]
}

declare const Example: Example;

export = Example;

I'll admit, the array spacing isn't great, but who looks at .d.ts files for their json files anyway?

like image 83
dx_over_dt Avatar answered Nov 08 '22 20:11

dx_over_dt