Is it possible to retrieve the precise key currently indexed within type declaration?

I am currently working on developing a simple type that would require a nested object key to reference the outer level.

For better understanding, let's take an example:

const obj = {
  foo: {
     name: 'bar',
     ref: 'foo' // < this should reference the key of the parent
  }
}

In a static object type, this wouldn't be a problem as we only need to check for 'foo', but I am aiming to make it dynamic with generic type arguments.

I attempted the following:

type InnerObject<K> = {
   name: string,
   ref: K,
}

type OuterObject<T, K extends keyof T> = {
   [key in K]: InnerObject<K>
}

This almost works fine, enforcing type checking on the union of current keys:

https://i.sstatic.net/bZBxR.png

The problem is that it also permits passing the other object key to the ref property when it shouldn't.

https://i.sstatic.net/zqMzm.png

I've been contemplating creating a third type generic and using the Exclude utility type, like so:

type InnerObject<T, K extends keyof T, CurrentKey> = {
   name: string,
   ref: Exclude<CurrentKey, K>
}

However, the issue lies in figuring out how to pass the current key of the indexed object without explicitly writing a reducer/map function on the outer object.

Is this achievable or simply not possible in ?


Here is a link to the playground relevant to this topic.

Answer №1

If you have a specific type such as Example that needs to be transformed into a structure like this, the process can be achieved as follows:

type NewObject<T extends object> = {
    [Key in keyof T]: InnerData<Key>
}

The concept here is that we are essentially mapping the InnerData<Key> over each individual Key within keyof T.

An important distinction from your initial approach is that you were working on the entire union of keyof T, rather than each element separately. It’s akin to the variance between {[X in Y]: F<X>}, where each property may yield a distinct type, and {[X in Y]: F<Y>}, which does not.

This methodology will generate the desired outcome:

const newObj: NewObject<Example> = {
    firstItem: {
        title: 'sample',
        reference: 'example',
    },
    secondItem: {
        title: 'alternate',
        reference: 'example' // error!
    }
}

Will this approach meet your requirements effectively?

Link to Playground with Code

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

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 ...

Issue with populating virtual IDs in NestJS mongoose schema containing an array of schemas

In the schema provided below, I have defined the structure for Map, Marker, and Desk: export type MapDocument = Map & Document @Schema({ timestamps: true, versionKey: false, id: true }) export class Map { constructor(partial?: Partial< ...

Angular: How to Disable Checkbox

Within my table, there is a column that consists solely of checkboxes as values. Using a for loop, I have populated all values into the table. What I have accomplished so far is that when a checkbox is enabled, a message saying "hey" appears. However, if m ...

NestJS enforces HTTPS for Swagger redirects, whereas other endpoints are allowed to work on HTTP

I'm running into a strange problem with the Swagger interface on my NestJS server, which is hosted on a Windows Server environment and managed by PM2. While all other endpoints work fine over HTTP, the Swagger interface can only be accessed via HTTPS. ...

Leveraging interfaces with the logical OR operator

Imagine a scenario where we have a slider component with an Input that can accept either Products or Teasers. public productsWithTeasers: (Product | Teaser)[]; When attempting to iterate through this array, an error is thrown in VS Code. <div *ngFor= ...

What is the process for importing WebAssembly functions into TypeScript?

I currently have a TypeScript project and am in the process of incorporating a WebAssembly Module to replace certain functionalities. Successfully importing the WebAssembly module involved moving the .wasm loading logic to its own .js file, which is then ...

Determine the type of sibling parameter

Creating a Graph component with configurations for the x and y axes. The goal is to utilize GraphProps in the following manner: type Stock = { timestamp: string; value: number; company: 'REDHAT' | 'APPLE' | ... ; } const props: ...

Guide on transforming a JSON string into an array of custom objects using the json2typescript NPM module within a TypeScript environment

I am looking to utilize the json2typescript NPM module to convert a JSON string into an array of custom objects. Below is the code I have written. export class CustomObject { constructor(private property1: string, private property2: string, private p ...

The dreaded error message [ERR_REQUIRE_ESM] has appeared, indicating that the require() function for an ES

I am currently developing a Discord bot using TypeScript and discord.js. However, when I attempted to compile the code this morning, I encountered the following error: C:\SECRET\Kostegator\dist\Util\getMeme.js:17 const node_fetch_1 ...

Is there a way to set the initial value of an input's ngmodel variable using only HTML?

Is there a way to assign an initial value of "1" to the variable named "some" using ngModel during initialization? *Update: I am specifically interested in how to achieve this using HTML only component.html : <input type="text" value="1" name="some" ...

Customizing Angular Forms: Set formcontrol value to a different value when selecting from autocomplete suggestions

How can I mask input for formControl name in HTML? When the autocomplete feature is displayed, only the airport's name is visible. After users select an airport, I want to show the airport's name in the input value but set the entire airport obje ...

Angular version 5 and above introduces a new feature called "openFromComponent" within the Snackbar component, facilitating seamless communication

Angular (v5.2.10) Snackbar --| Introduction |-- I am facing a scenario where an Angular component named "Parent" is initializing an Angular Material Snackbar known as snackBar. The snackbar is being passed in the component called SnackbarMessage, which ...

Whenever I try to load the page and access the p-tableHeaderCheckbox in Angular (primeng), the checkbox appears to be disabled and I am unable to

I attempted to use the disabled attribute on p-tableheadercheckbox in order to activate the checkbox. <p-tableHeaderCheckbox [disabled]="false"></p-tableHeaderCheckbox> <ng-template pTemplate="header"> <tr> ...

typescript loop with a callback function executed at the conclusion

I am struggling with this code and it's driving me crazy. addUpSpecificDaysOfWeek(daysInMonth: any, callbackFunction: any){ var data = []; var that = this; daysMonth.forEach(function(day){ that.statsService.fetchData(that.userid, d ...

Yes, indeed - Entering the schema of a retrieved field from an Object schema

After deciding to upgrade from Yup version 0.29 to 1.2, I encountered some challenges with its types. Seeking assistance in finding the best solution for typing yup schemas. In version 0.29, the universal type Schema fit everywhere, but now it no longer d ...

Utilizing @ngrx/router-store in a feature module: A comprehensive guide

The NGRX documentation for Router-Store only showcases an example with .forRoot(). Upon experimenting with .forFeature(), I realized that this static method does not exist. I am interested in defining certain actions and effects to be utilized within my f ...

Optimizing Node.js and Express routes by separating them into individual files: a

When using Express in a Node project along with Typescript, what are the best practices for express.Router? For instance, it is recommended to follow a directory structure like this: |directory_name ---server.js |--node_modules |--routes ---in ...

Is it feasible to evaluate a Typescript method parameter decorator at request time in a nodejs+nestjs environment rather than just at build time?

Looking to simplify my handling of mongodb calls with and without transactions in a single service method by writing a decorator. This would help eliminate the repetition of code and make things more efficient. Key points for usage: • Service class has ...

Sharing data between components in Angular 2 using the <router-outlet> technique

Having just started exploring Angular 2, I am eager to pass a boolean value from one component to another using <router-outlet> After some research, it seems like the best approach is to utilize a service. My aim is to toggle a boolean variable in ...

retrieve a nested object's property using a dynamic string

Here is the object model I am working with: export class FrcCapacity { constructor( public id?: number, public frcId?: number, public capGroupId?: number, public capGroup?: CapGroup, public salesProductId?: number, public p1?: num ...