Developing a custom data structure that identifies the keys of an object with a designated nested attribute

There is an intriguing scenario where dynamically defining types from a centralized JSON data store would prove extremely beneficial. Allow me to elaborate.

The JSON file I possess contains a roster of various brands.

// brands.json
{
    "Airbus": {
        "keywords": ["A320", "A380"],
        "type": ["planes"]
    },
    "Jaguar": {
        "keywords": ["fiesta"],
        "origin": "UK",
        "type": ["cars", "glasses"]
    },
    "Nissan": {
        "keywords": ["qashqai"],
        "type": ["cars"]
    }
}

Next, there are type definitions in place:

import brands from "./brands.json";

type BrandNames = keyof typeof brands;

type Brands = {
    [P in BrandNames]: {
        keywords: string[];
        origin?: string;
        type: string[];
    }
};

I've established a type called CompanyNames, which is automatically generated and encompasses "Airbus" | "Jaguar" | "Nissan".

Progressing smoothly so far...

Now, the objective is to form a type named CarBrands, representing "Jaguar" | "Nissan".

While

type CarBrands = Exclude<CompanyNames, "Airbus">;
could achieve this, it lacks the desired dynamism.

Hence, the aim is to filter out all keys from Brands that possess a nested type property not containing the string "cars".

Is such a maneuver achievable?

Answer №1

If we could just preserve the string literal types of the string literal types, then it would be possible to extract only the brands with car in the types field. However, Typescript widens the types of the values in the types array to string, losing this information when looking at the type of the json object.

As a fun exercise, with the use of as const in version 3.4 (not yet released) to maintain all string literal types, the solution would appear as follows:

let data = {
    "Airbus": {
        "keywords": ["A320", "A380"],
        "type": ["planes"]
    },
    "Jaguar": {
        "keywords": ["fiesta"],
        "origin": "UK",
        "type": ["cars", "glasses"]
    },
    "Nissan": {
        "keywords": ["qashqai"],
        "type": ["cars"]
    }
} as const;

type Data = typeof data;
type CarBrands = {
    [P in keyof Data]: 'cars' extends Data[P]['type'][number] ? P : never
}[keyof Data]

Once again, the above solution does not apply to imported json modules because Typescript does not preserve the literal types in the string arrays and there is currently no way to instruct it to do so during coding.

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

Tips for preventing Angular from requiring an additional tag for a child component

Consider a scenario where I have a parent and child component in Angular 12. Their templates are structured as follows: Parent: <h1>This is the parent component</h1> <div class="container"> <div class="row"> ...

What is the best way to retrieve an array that was created using the useEffect hook in React?

Utilizing the power of useEffect, I am fetching data from two different APIs to build an array. My goal is to access this array outside of useEffect and utilize it in the return statement below to render points on a map. However, when trying to access it ...

Retrieve the array from the response instead of the object

I need to retrieve specific items from my database and then display them in a table. Below is the SQL query I am using: public async getAliasesListByDomain(req: Request, res: Response): Promise<void> { const { domain } = req.params; const a ...

Incorporating the unshift method in JavaScript: A Step-by-

I'm looking to create a new function with the following requirements: Function add(arr,...newVal){ } array = [1,2,3]; add(array,0) console.log(array); //I want this to output [0,1,2,3] I tried creating the function similar to push like this: ...

Tips for aligning the types of objects transmitted from a Web API backend to a React/Redux frontend

After creating a backend for my app using .net, I now have CRUD operations available to me. When performing a POST action, the response includes an entire new item object: {"Id":"7575c661-a40b-4161-b535-bd332edccc71","Text":"as","CreatedAt":"2018-09-13T15 ...

React: The useContext hook does not accurately reflect the current state

I'm currently facing a dilemma as I attempt to unify data in my app. Whenever I click the button, the isDisplay value is supposed to be set to true; even though the state changes in my context file, it does not reflect in the app. Thank you for your ...

Adding a line break ( ) in a paragraph within a TypeScript file and then transferring it to HTML does not seem to be functioning properly

Angular Website Component: HTML file <content-section [text]="data"></content-section> TypeScript file data = `Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's stand ...

Creating a key-constrained type in Typescript for object literals with automatically deduced number values

Suppose we have an object literal defined as: export const SOURCE = { UNKNOWN: 'Unknown', WEB: 'Web', MOBILE: 'Mobile', ... } as const; and export const OTHER_SOURCE = { UNKNOWN: 0, WEB: 1, MOBILE: ...

Utilizing TypeScript's conditional return type with an object as a parameter, and incorporating default values

Is it possible to create a function where the return type is determined by a string, with some additional complexities involved? I'm looking to achieve the following: The parameter is contained within an object The parameter is optional The object it ...

I am encountering issues with the TypeScript repository build on my local machine, but it successfully passes when

I am encountering an issue with a TypeScript repository failing to build on my local machine. The error message I receive is as follows: $ tsc --pretty -p tsconfig.json ../../../../../../node_modules/@types/graphql/subscription/subscribe.d.ts:17:12 - erro ...

I encounter an issue when trying to declare an enum in TypeScript

At line 26 in my typescript file, the code snippet below shows an enum definition: export enum ItemType { Case = 'Case', Study = 'Study', Project = 'Project', Item = 'Item', } I am currently using Visual Stu ...

retrieving a single object from $resource by passing a non-ID parameter

I am utilizing $resource to retrieve an array of objects. The method I am invoking is as follows: fetchTeamResource(): ng.resource.IResourceClass<ITeamResource> { return this.$resource("/api/Teams:teamId"); } Below is how I am i ...

What is the correct way to invoke a function that accepts a combination of specific string values when all I have is a regular string?

Within the TypeScript function declaration provided below, the parameter type alignment consists of unioned literals. function printText(s: string, alignment: "left" | "right" | "center") { // ... } As per the documentation ...

I am experiencing difficulties in assigning values to a formArray

I am struggling to update values in an array form, as I am facing challenges setting new values. Although I attempted to set values using patch value, my attempts were unsuccessful. // Component.ts this.packageForm = this.formBuilder.group({ title: [&a ...

Ways to prevent an array from being reset

My issue involves the clothes and orders tables, along with an array based on Clothes and Orders models. Whenever I add a clothes element into the Orders array and specifically update the amount and price of the selected item, it also updates the Clothes a ...

Incorporate an external library

I am currently facing a challenge in my angular2 project where I need to import a 3rd party library. Here are the steps I have taken so far: ng new myproject npm install --save createjs-easeljs npm install @types/easeljs However, I am stuck at this poin ...

Using RxJS and the combineLatest function can be hit or miss in terms of reliability

When you call this function multiple times with the values of observables obs1 and obs2 being the same each time, the returned array may not always be the same. getUniqueProducts(obs1: Observable<any>, obs2: Observable<any>): Observable<any& ...

Balancing website speed with capturing product impression

I've been tasked with capturing impressions of all the products visible in the viewport on a website that features thousands of products. To achieve this, I implemented a directory and utilized the IntersectionObserver, which was referenced within the ...

Error Encountered When Trying to Import BrowserAnimationsModule in Angular 5: Unexpected Token "<"

As I try to integrate the BrowserAnimationModule into my Angular 5 project, a rather foolish error keeps popping up. Error: (SystemJS) Unexpected token < SyntaxError: Unexpected token < at eval (<anonymous>) at Object.eval ...

Automatically dismiss modal upon submission

In the process of implementing a CRUD operation, I am trying to automatically close the modal upon submission. Using data-dismiss on the submit button only closes the modal without executing the functionality. What I need is for the functionality to execut ...