Defining a TypeScript structure for a JSON object by referencing another entry within the same object

I'm currently working on defining a TypeScript structure for a JSON object. One part of the object includes a property called components, which is an array of strings. However, I want to enhance this structure by adding an additional property called overrides, where specific entries from the components array can have property overrides.

My challenge is to find a way to restrict the componentName key within the overrides object to only allow values that match one of the entries in the components array. Here's how I currently have it set up:

interface MyJsonObject {
    components: string[];
    overrides: {
        [componentName: string]: {
             [propName: string]: unknown;
        };
    };
}

What I want to achieve is to verify that the following configuration is valid:

const config: MyJsonObject = {
    components: ['test'],
    overrides: {
        test: {
            foo: 'bar',
        }
    }
}

And to ensure that the following configuration is considered invalid:

const config: MyJsonObject = {
    components: ['test'],
    overrides: {
        baz: {
            foo: 'bar',
        }
    }
}

Answer №1

Absolutely, generics are a great option:

type CustomJson<TIdentifier extends string> = {
    components: TIdentifier[];
    overrides: Record<TIdentifier, Record<string, unknown>>;
}

const data: CustomJson<'key'> = {
    components: ['key'],
    overrides: {
        baz: {
            foo: 'bar',
        }
    }
}

However, specifying the type of TIdentifier can be cumbersome. Using a function can help infer the type for us:

type CustomJson<TIdentifier extends string> = {
    components: TIdentifier[];
    overrides: Record<TIdentifier, Record<string, unknown>>;
}

function checkStructure<TIdentifier extends string>(myData: CustomJson<TIdentifier>): CustomJson<TIdentifier> {
    return myData;
}

const resultA = checkStructure({
    components: ['key'],
    overrides: {
        key: {
            foo: 'bar',
        }
    }
});

const resultB = checkStructure({
    components: ['key'],
    overrides: {
        baz: {
            foo: 'bar',
        }
    }
});

There is an ongoing issue to simplify this process without the need for a function to infer the generic parameter.

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

Overloading TypeScript functions with Observable<T | T[]>

Looking for some guidance from the experts: Is there a way to simplify the function overload in the example below by removing as Observable<string[]> and using T and T[] instead? Here's a basic example to illustrate: import { Observable } from ...

Incorporating Precision to Decimal Numbers in TypeScript Angular

Having some trouble with this issue and I've tried various solutions without success. This problem is occurring within an Angular project. The requirement is to always display a percentage number with two decimal places, even if the user inputs a who ...

Retrieve the variance between two arrays and store the additions in AddedList and the removals in RemovedList using typescript

I am still getting the hang of Typescript and I am trying to figure out the best solution for my issue. I have two arrays, A and B, and I need to identify the difference between them in relation to array A. The goal is to separate the elements that were ad ...

Is there a way to customize the appearance of a MUI5 Tooltip using emotion?

I went through the information in this Stack Overflow post and experimented with the styled method. The code snippet I used is as follows: import * as React from 'react'; import { styled } from '@mui/material/styles'; import Tooltip, { ...

`How can we efficiently transfer style props to child components?`

Is there a way to pass Props in the Style so that each component has a unique background image? Take a look at this component: countries.astro --- import type { Props } from 'astro'; const { country, description } = Astro.props as Props; --- & ...

Setting a TypeScript version in Atom: Step-by-step guide

I'm currently grappling with using a specific version of TypeScript in Atom. For an older project that relies on Backbone, the latest TypeScript version doesn't compile properly, so I need to use an earlier one. The closest solution I've co ...

Building a hierarchical tree structure using arrays and objects with Lodash Js

I am attempting to create a tree-like structure using Lodash for arrays and objects. I have two arrays, one for categories and the other for products, both with a common key. The goal is to organize them into a tree structure using string indexing. let ca ...

Steps for transferring data between two components

I'm looking for a way to transfer an object's id from one component to another. <ng-container matColumnDef="actions"> <mat-header-cell *matHeaderCellDef></mat-header-cell> <mat-cell *matCellDef="let user"> ...

The Typescript compiler has trouble locating the definition file for an npm package

Recently, I released an npm package that was written in typescript. However, I have been facing difficulties in getting the definition recognized by typescript (webback and vscode). The only workaround that has worked for me so far is creating a folder wit ...

Is it possible to create a single directive that can handle both Structural and Attribute behaviors?

Trying to develop an Angular Directive that will handle various functionalities based on config input values Dynamically add elements to the DOM based on input values (similar to ngIf) Apply styling to rendered elements Add attribute properties such as d ...

Using TypeScript along with Nuxt.js and Vuex to access methods from an imported class

Currently, I am in the process of developing a nuxt.js application with typescript and my goal is to segregate the API Calls from the vuex store. However, I've encountered an issue where it seems like I cannot utilize the methods when importing the cl ...

How to extract a JavaScript object from an array using a specific field

When dealing with an array of objects, my goal is to choose the object that has the highest value in one of its fields. I understand how to select the value itself: Math.max.apply(Math, list.map(function (o) { return o.DisplayAQI; })) ... but I am unsur ...

What could be causing the need for RxJs TypeScript files to be requested exclusively when my website is hosted on IIS?

When I develop my site using Visual Studio / IIS Express, everything runs smoothly without any unusual requests or 404 errors. However, once I publish the site to IIS and try to run it, I start receiving multiple requests for typescript files (.ts), prima ...

I'm having trouble configuring the header in my Node/Express route

Using Node and the Express framework for my backend, along with React for my frontend, all coded in Typescript. The elastic search client is responsible for fetching data on the backend, but I don't believe that's where the issue lies. I'm ...

Typescript type for selecting only string[] keys in an object

I am looking for a specific type: interface Filter<P extends object> { label: string; options: FilterOption[]; key: StringArrayKeyOf<P>; } The definition of StringArrayKeyOf is as follows: type StringArrayKeyOf<T extends object> = ...

Exploring Click Events in Angular with OpenLayers Features

After creating a map with parking points as features, I now want to implement a click function for the features. When a feature is clicked, I want to display a popup with the corresponding parking data. I've tried searching online for information on ...

Expanding one type by utilizing it as an extension of another type

I am looking to create a custom object with predefined "base" properties, as well as additional properties. It is important for me to be able to export the type of this new object using the typeof keyword. I want to avoid having to define an interface for ...

How can we ensure that only one of two props is specified during compilation?

I've designed a customized Button component. interface Button { href?: string; action(): void; } I'm looking to ensure that when a consumer uses this Button, they can only pass either href or action as a prop, not both. I want TypeScri ...

Utilizing Typescript and sinon to mock the functionalities of jsonwebtoken

Looking for help with mocking the function verify in Typescript's jsonwebtoken library. I've installed typescript, jsonwebtoken, sinon, mocha, and chai along with their corresponding types. However, when trying to stub the function, an error occu ...

The type entity i20.CdkScrollableModule cannot be resolved to symbol in the nx workspace

After extensively researching online, I still haven't found a solution to this particular issue. I've attempted various troubleshooting steps, including deleting node_modules and package-lock.json, updating dependencies, and running nx migrate. ...