Home > Back-end >  TypeScript error on json import (SvelteKit)
TypeScript error on json import (SvelteKit)

Time:10-09

I am pretty new to TypeScript and have searched quite a while now but could not find a solution specific to my problem.

In my SvelteKit application, I have a json file like that:

{
  "some-key": {
    "title": "some title",
    "content": "some content"
  }
}

The file is being imported into a TypeScript file ( page.ts from SvelteKit routing) and I want to access some-key dynamically:

import { error } from '@sveltejs/kit';
import type { PageLoad } from './$types';
import data from '../data.json';

export const load: PageLoad = ({ params }) => {
  if (data[params.slug]) {
    return data[params.slug];
  }
 
  throw error(404, 'Not found');
}

Both lines with data[params.slug] are yelling at me in TypeScript:

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ "some-key": { title: string; content: string; }; }'.
  No index signature with a parameter of type 'string' was found on type '{ "some-key": { title: string; content: string; }; }'.

I think TypeScript needs to know about the keys, somehow? Maybe the issue here is easy to fix. But I am stuck and hope someone could help me.

CodePudding user response:

The issue seems to be that the type of the JSON is { "some-key": { title: string; content: string; }; } but you want it to be { [key: string]: { title: string; content: string; }; }.

Probably what I would do is use a .ts file instead of JSON. That way you can also ensure that it is correctly formed and you get nicer typing annotations. Something like this:

interface PageData {
    title: string,
    content: string,
}

export const data: Record<string, PageData> = {
    "some-key": {
        title: "Some title",
        content: "Some content",
    },
}

This should work.

CodePudding user response:

I solved it by re-assigning the JSON object to a variable and type that with an interface:

import { error } from '@sveltejs/kit';
import type { PageLoad } from './$types';
import data from '../data.json';

interface Data {
  [slug: string]: {
    title: string;
    content: string;
  };
}

const dataObject: Data = data;

export const load: PageLoad = ({ params }) => {
  if (dataObject[params.slug]) {
    return dataObject[params.slug];
  }
 
  throw error(404, 'Not found');
}

Please comment, if you see a better/simpler way of doing it.

  • Related