How can I choose one record based on another record in a database?

I have a unique structure where consts and record types are combined:

const PageType = [
  'type1',
  'type2',
  'type3'
] as const;

export type PageType = typeof PageType[number];

interface PageInfo {
  title: string
}

interface DetailsInfo {
  bla: string;
}


export const PagesData: Record<PageType, PageInfo> = {
  type1: {
    title: 't1'
  },
  type2: {
    title: 't2'
  },
  type3: {
    title: 't3'
  }
}

export const DetailsData: Record<PageType, DetailsInfo> = {
  type1: {
    bla: 'bla1',
  },
  type2: {
    bla: 'bla2',
  },
  type3: {
    bla: 'bla2',
  },
};

My goal is to be able to access data like this: Pages[Details.type1].title <-- this currently gives me a compiler error

Essentially, I want to dynamically access Pages based on the current value of Details. For example, accessing Datails["type1"] should return the related Pages.type1

Any thoughts or suggestions?

Answer №1

Below is a revamped approach to address the issue you are facing in your code snippet, which results in a compiler error. Initially, I found it confusing that the instance variables were given capitalized names resembling types, so I have made corrections accordingly.

Due to type erasure, once a DetailsInfo object loses its lookup key association, it becomes challenging to determine its source entry (as suggested in the function definition within my revised example). To enable JavaScript logic control based on PageType keys for lookup and data retrieval purposes, runtime preservation of this information is crucial (i.e., as an explicitly defined value in the javascript).

const PAGE_TYPE = [
  'type1',
  'type2',
  'type3'
] as const;

export type PageType = typeof PAGE_TYPE[number];

interface PageInfo {
  title: string
}

interface DetailsInfo {
  bla: string;
}

export const pages: Record<PageType, PageInfo> = {
  type1: {
    title: 't1'
  },
  type2: {
    title: 't2'
  },
  type3: {
    title: 't3'
  }
}

export const details: Record<PageType, DetailsInfo> = {
  type1: {
    bla: 'bla1',
  },
  type2: {
    bla: 'bla2',
  },
  type3: {
    bla: 'bla2',
  },
};

function getPageInfo(detailsInfo:DetailsInfo): PageInfo{
//the current implementation leads to a compiler error with no apparent solution to return the correct PageInfo
}

const pageInfo = getPageInfo(details["type1"]);

On the contrary, here is an alternative working approach where the PageType value must be preserved at runtime to enable successful lookups. While I cannot guarantee that this aligns perfectly with your real-world scenario, it highlights what was lacking in your initial strategy.

const PAGE_TYPE = [
  'type1',
  'type2',
  'type3'
] as const;

export type PageType = typeof PAGE_TYPE[number];

interface PageInfo<Kind extends PageType> {
  title: string
  kind:Kind
}

interface DetailsInfo<Kind extends PageType> {
  bla: string;
  kind:Kind
}

type PageLookup = {
  [K in PageType]: PageInfo<K>
}

type DetailsLookup = {
  [K in PageType]: DetailsInfo<K>
}

export const pages: PageLookup = {
  type1: {
    kind:"type1",
    title: 't1'
  },
  type2: {
    kind:"type2",
    title: 't2'
  },
  type3: {
    kind:"type3",
    title: 't3'
  }
} as const;

export const details: DetailsLookup = {
  type1: {
    kind:"type1",
    bla: 'bla1',
  },
  type2: {
    kind:"type2",
    bla: 'bla2',
  },
  type3: {
    kind:"type3",
    bla: 'bla2',
  },
} as const;

function getPageTitle<Kind extends PageType>(detailsInfo:DetailsInfo<Kind>): string{
  return pages[detailsInfo.kind].title
}

const pageTitle = getPageTitle(details["type1"]);

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

Develop a TypeScript class by incorporating a static function from an external library, while ensuring type safety

I am looking to enhance the capabilities of the rxjs5 Observable class by adding a static function. While this can be easily accomplished in plain JavaScript: var myStaticFn = function() { /* ... */ }; Observable.myStaticFn = myStaticFn; this approach w ...

Unleash the full power of Angular Components by enhancing them with injected

I am facing a challenge with handling the destruction event of an Angular component in my external module that provides a decorating function. I've run into issues trying to override the ngOnDestroy() method when it includes references to injected ser ...

Angular 2 i18n: Localization of <option> values

I am in the process of transitioning my application from ng2-translate to native i18n support. I have encountered an issue when trying to translate a <md-select> element with multiple options: <md-select placeholder="Salutation" i18n-placeholder& ...

Is it possible to compile using Angular sources while in Ivy's partial compilation mode?

Error: NG3001 Unsupported private class ObjectsComponent. The class is visible to consumers via MasterLibraryLibModule -> ObjectsComponent, but is not exported from the top-level library entrypoint. 11 export class ObjectsComponent implements OnInit { ...

What is the proper way to utilize this xd-file package?

I'm currently working on manipulating an Adobe XD file using a specific package. If you're interested, here's the link to the package: xd-file My goal is to incorporate this code snippet into a JavaScript file, utilizing Node.js. The meth ...

Removing a field from a collection using firebase-admin: Tips and tricks

I currently have a collection stored in Firebase Realtime Database structured like this: https://i.sstatic.net/jNiaO.png My requirement is to remove the first element (the one ending with Wt6J) from the database using firebase-admin. Below is the code s ...

Managing non-mandatory information in a structured domain representation: What's the best approach?

When working on applications or domain models, I often ponder the most effective approach to handling incomplete or optional data. Typed languages like TypeScript and C# offer the advantage of defining models with strict types. While this can be beneficial ...

Loading data into the Nuxt store upon application launch

Currently, I'm working on an app using Nuxt where I preload some data at nuxtServerInit and store it successfully. However, as I have multiple projects with similar initial-preload requirements, I thought of creating a reusable module for this logic. ...

Executing a for loop concurrently by utilizing async/await promises

In my current code, I am using a for loop structured like this: async myFunc() { for (l of myList) { let res1 = await func1(l) if (res1 == undefined) continue let res2 = await func2(res1) if (res2 == undefined) continue ...

Grafana: Simplifying time series data by eliminating time ranges or null values

Is there a way to remove the time on the axis of a realtime time series graph when there is no data between 11:30-13:00? The data source is clickhouse. enter image description here enter image description here I attempted to connect null values, but it wa ...

Tips for sending a function as a value within React Context while employing Typescript

I've been working on incorporating createContext into my TypeScript application, but I'm having trouble setting up all the values I want to pass to my provider: My goal is to pass a set of values through my context: Initially, I've defined ...

The parameter type x cannot be assigned to the argument type '(x) => ObservableInput<{}>'

Looking for some insights on this issue Currently working with ngrx and attempting to utilize multiple switchMaps to call various action classes. Defined Actions: export class BlogAddedAction implements Action { readonly type = BLOG_ADDED_ACTION; ...

Investigating SCSS Issues: The Problem with Absolute Imports

I am working on a project with the following structure: - my/project - assets - images - image-name.svg - source - components - MyComponent - MyComponent.module.scss - ... - ... ...

The struggle of accessing child components using ViewChild in Angular

I am facing an issue with a dialog box that is supposed to display a child component separately. Below is the code for the child component: @Component({ selector: 'userEdit', templateUrl: './edituser.component.html', styleUrls: [ ...

The current state of this scenario is not clearly defined within the parent class

Here is the scenario that caught my attention: abstract class Base { public _obj = { name: 'Test' } print1() { console.log(this._obj) } print2() { console.log(this) } } class Child extends Base { print2( ...

Unable to classify mapRef.current

I am facing an issue with my react component that contains a leaflet map. TypeScript is warning me about line mapRef.current.setView(coords, 13), stating it is an "unsafe call of an any typed value" import 'leaflet/dist/leaflet.css'; import { Map ...

The ngOnInit child function fails to activate when trying to assign a fresh object

On the parent page, I am passing user data to a child component in this way: <ng-container *ngIf="leaderboard"> <app-leaderboard-preview [user]="user" (click)="goToLeaderboard()"></app-leaderboard-preview> </ng-container> In t ...

Tips on effectively utilizing Chart.js with Typescript to avoid encountering any assignable errors

I'm encountering an issue while utilizing the Chart.js library in my Angular application with Typescript. The error message I'm receiving is as follows: Error: Object literal may only specify known properties, and 'stepSize' does not e ...

Using TypeScript to Calculate Hours and Minutes Between Two Time Values

In this scenario, the start time is 11:30 and the end time is 13:00. The expected output should be 1:30. Is there a TypeScript code snippet that can achieve this result? ...

Angular-Material: Custom Date and Time Picker Component with Seconds disabled

Is there a way to customize the datetime picker to only display Date, Hours, and Minutes, while removing seconds? Currently, the picker includes seconds as well. <mat-form-field appearance="outline" floatLabel="always"> <ma ...