JSON TypeScript compliant interface

My problem is quite common, but the solutions found on stackoverflow are not suitable for my specific case.

I have a collection of objects that I need to manipulate, save, and load as json files. Here's an example of the interface:

type jsonValue = string | number | jsonValue[] | json | undefined;

interface json {
    [index: string]: jsonValue
}

interface I_Foo extends json {
    p1: string;
    p2: number;
}

When trying to implement this, I encounter the following error:

An interface can only extend an object type or intersection of object types with statically known members.

How should I approach this issue? It is important that all interfaces adhere to the json format for seamless code iteration and serialization. At the same time, I need to define specific interfaces for each object.

Edit: Just to clarify, I require a solution to create an interface with any number of properties that align with json standards, which can then be implemented by a class for effective usage.

Answer №1

Despite not being able to replicate the issue with the interfaces, the recommended solution is to switch to using types.

Adjustment of JsonValue:

type JsonValue = string | number | JsonValue[] | JsonObject | undefined;

type JsonObject = {
  [index: string]: JsonValue;
};

Introducing a utility type for clearer types:

type Prettify<T> = T extends infer R ? { [K in keyof R]: R[K] } : never;

This allows the creation of a type that takes a generic parameter and combines it with JsonObject:


type Json<T> = Prettify<T & JsonObject>;

type I_Foo = {
  p1: string;
  p2: number;
};

type I_FooWithBase = Json<I_Foo>;

If you were to implement a class that follows I_FooWithBase, an index signature must be added to the class:

class Foo implements I_FooWithBase {
  public p1: string = '';
  public p2: number = 1;
  [index: string]: JsonValue;
}

However, this approach allows access to any irrelevant string key:

const a = new Foo();
a.dasd // no error

Instead, have the class implement I_Foo which does not have an index signature:

class Foo implements I_Foo {
  public p1: string = '';
  public p2: number = 1;
}

const a = new Foo();
a.dasd // expected error

playground

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Strategies for resolving a mix of different data types within a single parameter

Here, I am setting up the options params to accept a value that can either be a single string or another object like options?: string[] | IServiceDetail[] | IServiceAccordion[]; However, when attempting to map these objects, an error is encountered: Prope ...

Error TS2339 occurs when attempting to migrate to TypeScript due to the absence of the 'PropTypes' property on the 'React' type

Currently in the process of converting a javascript/react project to a typescript/react/redux project. Encountering an issue with this particular file: import React from 'react'; import GoldenLayout from 'golden-layout'; import {Provi ...

Authentication Redirect Failure when using Passport to an absolute URL

I am looking to redirect the user to a different URL with the code/token received after logging into Facebook using Passport in Express.js. app.get('/auth/facebook/callback', function (req, res, next) { var authenticator = passport.authentic ...

What is the best way to refresh a personalized form element using Angular?

I have developed a custom form control with validation that utilizes a standalone FormControl to manage the value and perform certain validations. Is there a method in Angular to reset the inner FormControl when the control is being reset from another For ...

Consolidating Typescript modules into a single .js file

Recently, I was able to get my hands on a TypeScript library that I found on GitHub. As I started exploring it, I noticed that there were quite a few dependencies on other npm packages. This got me thinking - is there a way to compile all these files int ...

Introducing an extra 'pipe' in rxjs angular may result in generating errors

Encountering an unusual issue with Angular. The following code functions correctly: this.form.valueChanges .pipe( startWith(this.form.value), pairwise(), tap(() => console.log('aa')) ...

Get the download URL from Firebase Storage and save it into an array within Firestore

I am currently working on a project to upload multiple image files to Firebase Storage and then store their download URLs in a single array within Firestore. uploadImages(name, images) { for (let i = 0; i < images.length; i++) { const file = ...

Using TypeScript and the `this` keyword in SharePoint Framework with Vue

I'm currently developing a SharePoint Framework web part with Vue.js. Check out this code snippet: export default class MyWorkspaceTestWebPart extends BaseClientSideWebPart<IMyWorkspaceTestWebPartProps> { public uol_app; public render(): ...

Transitioning to mui5's sx prop instead of makeStyles is generating a typescript error - none of the overloads match this call when passing an object with

I encountered an issue while converting a component to mui 5. Here is the original code snippet: const useStyles = makeStyles({ imageContainer: { display: "flex", width: "65%", float: "left", marginRight ...

When transmitting data from NodeJS, BackBlaze images may become corrupted

I have been facing a challenge in my React Native app where I am attempting to capture an image and then post it to my NodeJS server. From there, I aim to upload the image to BackBlaze after converting it into a Buffer. However, every time I successfully u ...

How can one ensure that the element declared in the "let" clause is displayed in an HTML Angular template?

I am working on a component that can render a mat-table. Each cell can have a specified value, or if it is present, the component calls an ngTemplateOutlet and passes it a rendering function obtained from the calling object. export interface ColumnConfig { ...

Arrangement of items in Angular 2 array

Received a JSON response structured like this JSON response "Terms": [ { "Help": "Terms", "EventType": "Success", "Srno": 1, "Heading": "Discount Condition", "T ...

Utilizing Dynamic Class Names in Angular 7 with Typescript

In the process of developing an Angular 7 application, I have created a form component that is intended to be used for various entities. As part of this, I defined a variable route: {path: ':entity/create', component: FormComponent} While this ...

Can you explain how to invoke a class with express().use function?

Currently, I am delving into learning Node JS with TypeScript but have hit a roadblock with a particular issue. In my app.ts file, I have initialized the express and attempted to call the router class inside the app.use() method, only to encounter an error ...

The constructor in a Typescript Angular controller fails to run

Once the following line of code is executed cockpit.controller('shell', shellCtrl); within my primary module, the shell controller gets registered with the Angular application's _invokeQueue. However, for some reason, the code inside t ...

Why does TypeScript require a generic type parameter when arguments have already been provided?

When I attempted to use the argument p to infer type P, TypeScript still prompted me to provide type P. Why is that? const numberStringConverter = <T extends string | number,P extends {x: any}>(p: P): T => { if(typeof p.x === 'string') ...

Swagger Issue Resolved: Restriction on Number of Params Set

After setting up this option for my route, I noticed that when accessing the first parameter (page), it correctly returns the value entered in Swagger UI. However, when trying to access the second parameter (genre), it seems to interpret it as a string &ap ...

Preventing Button Clicks in Angular 2 When Form Data is Modified

I am looking to determine if at least one field in my form has been altered. When this condition is met, the disableButton variable will be set to true, and false if there are no changes in the form. Here is the snippet of code I am currently using: // Th ...

Best practices for updating the value of a specific key within an object that contains recursion in JavaScript/TypeScript

I have a tree component that uses the following data structure type TreeNode = { id: string, parentId: string, renderer: () => React.ReactNode, expanded: boolean, children?: Array<TreeNode>, } Now, I am looking to add functionality for ...

Converting typescript path aliases into local file paths

Just dipping my toes into typescript and grappling with module resolution. The problem seems straightforward (or so I think), but there's something off about my tsconfig.json. If my folder structure looks like this: + release + definitions + ...