How can I access the keys of an interface in which the type of interface[key] is defined?

Consider this scenario:

interface Interface {
  a: number
  b: number
  c: string
  d: string
  e: number[]
}

If I want to retrieve the keys of Interface based on the type of their corresponding values in Interface, how can I achieve that? This is similar to the functionality of Pick<T, K>, but instead of selecting keys based on their type, we are interested in keys whose values match a certain type.

An example of what I am trying to accomplish is shown below:

type KeyOfWhereValueMatches<T, U extends U[keyof U]> = // ???
KeyOfWhereValueMatches<Interface, number> // 'a' | 'b'
KeyOfWhereValueMatches<Interface, string> // 'c' | 'd'
KeyOfWhereValueMatches<Interface, number[]> // 'e'

Answer №1

To achieve this functionality, you can use the following code snippet:

type GetKeysWhereValueMatches<
    Input,
    Value,
    Result = { [property in keyof Input]: Value extends Input[property] ? property : never; }
    > = Result[keyof Result]

Here's how it operates: Input represents your interface, while Value signifies the type for which you need to retrieve keys.

The variable Result is a type that iterates over each key within the interface type. If the assigned value matches the type of that key (e.g. string extends Interface[k]), the resulting type for that field becomes a string literal of its key. Otherwise, it defaults to a never.

For instance, invoking

GetKeysWhereValueMatches<Interface, string>
would yield:

interface Result {
    name: "name";
    age: never;
    gender: "gender";
}

Lastly, Result[keyof Result] utilizes lookup types to ascertain the types corresponding to all available keys in Result. These could either be the appropriate key's string literals or never. Given that never isn't encountered, the lookup simply returns the string literals.

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

Eliminate the need for 'any' in TypeScript code by utilizing generics and partials to bind two parameters

I'm working with TypeScript and have the following code snippet: type SportJournal = { type: 'S', sport: boolean, id: string} type ArtJournal = { type: 'A', art: boolean, id: string} type Journal = SportJournal | ArtJournal; type J ...

Typescript's Confusion with Array Types: Understanding Conditional Types

Here is the setup I have. The concept is to receive a generic and options shape, deduce the necessary options based on the generic and the type key of the options shape, and appropriately restrict the options. type OptionProp<T extends string | boolean& ...

Unit testing in Angular 2+ involves testing a directive that has been provided with an injected window object

Currently, I am faced with the challenge of creating a test for a directive that requires a window object to be passed into its constructor. This is the code snippet for the directive: import { Directive, ElementRef, Input, OnChanges, OnDestroy, OnInit ...

What is the best way to inject services into non-service class instances in Angular 2?

Here is my current approach, but I'm curious about the recommended practice for working with Angular2? ... class MultitonObject { _http: Http; constructor (appInjector: Injector) { this._http = appInjector.get(Http); } } var ap ...

Using Typescript to extract the type from within the function type parameters

I am currently utilizing an imported type definition that contains a function type definition with a fairly complex parameter type: export interface SomeTypeDefinition { someFunction: ( param1: string, param2: { key1: number, key2: s ...

Encountered a problem with AngularUniversal prerendering: UnhandledPromiseRejectionWarning: Unable to locate NgModule metadata for 'class{}'

Objective The task may seem lengthy, but it's straightforward! Currently, I am utilizing Angular Universal for Server-Side Rendering (SSR) by following a tutorial. The Universal/express-engine has been installed, main.js is generated in the dist/pro ...

Construct an outdated angular project from scratch

I'm facing an issue with an old Angular project that I'm trying to build. After pulling down the code, running npm install @angular/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="fc9f9095bccdd2cbd2c8">[email p ...

Ways to describe an item using a mix of determined and undetermined attributes

I am attempting to create a TypeScript type that includes properties I know and properties I do not know. Here is what I have tried: type MetaType = { res?: HttpResponse; req?: HttpRequest; [key: string]: string | number | boolean | string[] } ...

A step-by-step guide on troubleshooting and resolving issues with "ng build"

Need help resolving the ng build project issue in Angular without modifying angular.json. Encountered the following error: Your global Angular CLI version (8.3.16) is higher than your local version (8.1.3). The local Angular CLI version will be used. To ...

WebStorm encountering TypeScript error with "nullish coalescing operator"

I am currently facing a problem while using WebStorm with TypeScript v3.7.5. In this particular version, TS introduced the `??` operator. I have implemented it in my project but it seems like WebStorm is not able to understand it and displays an `expressio ...

Steps to stop mat-spinner upon receiving Job Success/Failure Notification from the backend

I have a task that runs asynchronously and takes a long time to complete. When the task starts, I display a mat-spinner with a timeout set at 60000 milliseconds. However, we now have a notification service that provides updates on the job status. I would l ...

Discovering oddities in the Pandas dataframe: Identifying columns with a mixture of datatypes

While working with a large dataframe, I encountered an issue when reading it which generated this message: DtypeWarning: Columns (0,8) have mixed types. Specify dtype upon import or set low_memory=False. The column is expected to contain floats, but I sus ...

Is there a way to prompt the browser's default handler to execute prior to the event propagation?

When working with a textbox (<input type="text">) in the browser, it's important to note that keystrokes are not processed until after all JS event handlers have completed execution. In my application, I encountered a scenario where a ...

What is the reason for the absence of a PasteEvent type in the types/jquery library?

Why doesn't jQuery have a specific type for PasteEvent or ClipboardEvent? While there is a standard type for paste events (ClipboardEvent), jQuery does not have a specific event type for it. view image description here view image description here I ...

Changing the Image Source in HTML with the Power of Angular2

Despite my efforts, I'm unable to display the updated image in my HTML file. In my TypeScript file, the imageUrl is updating as expected and I've verified this in the console. However, the HTML file is not reflecting these changes. In my researc ...

Discover the step-by-step process for moving data between collections in MongoDB

I am currently working on nestjs and have two collections, one for orders and the other for payments. My goal is to retrieve a single entry from the orders collection and save that same entry into the payments collection. Below is the code for the service ...

Angular 7 is unable to connect to <property> as it is not recognized as a valid property of <component> in the imported module

I have been facing an issue with my module setup where ModuleA is importing ModuleB to use a component declared within it. The specific problem arises when ModuleAComponentC attempts to utilize ModuleBComponentA. While logic dictates that ModuleA should im ...

What is the best way to retrieve the final value stored?

This is how I am using my Selector:- private loadTree() { this.loading = true; this.store.select(transitionListSelector).pipe().subscribe(data => { console.log(data); data.map(item => { console.log(item); this.tr ...

Utilizing NPM Workspaces to efficiently distribute TypeScript definition files (`*.d.ts`) across multiple workspaces

In my TypeScript monorepo utilizing NPM Workspaces, I have two packages: A and B. Package B requires type definitions from package A. To accomplish this, I included a reference to A's definition file in the tsconfig.json of package B. However, somet ...

Working with type-agnostic values in a type-agnostic list within a type-agnostic class using Typescript

I'm currently attempting to add a generic object to a list of other generic objects within a generic class. There seems to be an issue with the semantics, but I can't pinpoint exactly what the problem is. type EventCallback<I, O> = (event ...