The peculiar syntax that arises when conditional types are merged with mapped types

Check out this demo

You can also try it in the sandbox

See how the code works:

type FunctionPropertyNames<T> = {
  [K in keyof T]: T[K] extends Function ? K : never;
}[keyof T];

interface Part {
  id: number;
  name: string;
  subparts: Part[];
  updatePart(newName: string): void;
}

type T1 = FunctionPropertyNames<Part>;

const myVar:T1 = 'updatePart'

I'm puzzled by the [keyof T] part in

type FunctionPropertyNames<T> = {...}[keyof T]
. It's a unique syntax I haven't encountered before and couldn't find much about it in the resources. Can you show me another instance of its application? Or direct me to where I can learn more about it. Maybe shed some light on how it functions.

Your assistance is greatly appreciated!

Answer №1

When T is an object, the expression keyof T evaluates to all the property names in

T</p>
<pre><code>type Thing = { fieldOne: string; fieldTwo: number };

type ThingFields = keyof Thing; //similar to: type ThingFields = "fieldOne" | "fieldTwo"

The utility FunctionPropertyNames<T> may seem confusing, but when we break it down for Part, it leads to "updatePart".


type T1 = FunctionPropertyNames<Part>;

Breaking down

FunctionPropertyNames<Part>

type T1 = {
  [K in keyof Part]: Part[K] extends Function ? K : never;
}[keyof Part];

Expanding the keyof expressions

type T1 = {
  [K in "id" | "name" | "subparts" | "updatePart"]: Part[K] extends Function ? K : never;
}["id" | "name" | "subparts" | "updatePart"];

After evaluating the conditional expressions, only Part["updatePart"] satisfies extends Function condition and results in "updatePart". Other cases result in never.

type T1 = {
  id: never;
  name: never;
  subparts: never;
  updatePart: "updatePart";
}["id" | "name" | "subparts" | "updatePart"];

Next step is to evaluate property indexes.

For instance,

{ fieldOne: "abc" }["fieldOne"]
returns "abc", while
{ fieldTwo: never }["fieldTwo"]
gives never.

In this case, indexing with "updatePart" yields a non-never result: "updatePart". Everything else results in never.

type T1 = never | never | never | "updatePart";

Simplified to

type T1 = "updatePart";

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

Leveraging functionality from an imported module - NestJS

Currently, I am utilizing a service from a services module within the main scaffolded app controller in NestJS. Although it is functioning as expected - with helloWorldsService.message displaying the appropriate greeting in the @Get method - I can't ...

Changing the type of an object's property in TypeScript on the fly

I am working on a TypeScript function that is designed to dynamically modify the property of an object. Here is the function: const updateProperty = (value: any, key: keyof Type1, obj: Type1) => { obj[key] = value; } Below is the definition of "Typ ...

What is the best way to retrieve entire (selected) objects from a multiselect feature in Angular?

I'm facing an issue with extracting entire objects from a multiselect dropdown that I have included in my angular template. Although I am able to successfully retrieve IDs, I am struggling to fetch the complete object. Instead, in the console, it dis ...

Issue encountered while executing ./node_modules/.bin/cucumber-js within GitLab CI

I've encountered an issue while setting up a continuous integration build for my node project. Despite the fact that npm run test runs smoothly in my local setup, I am facing an exception in GitLab CI. The error arises from the following test command ...

"Would someone be able to advise me on how to correctly reference the PrimeNG AutoCompleteModule within my

I've been developing an application that relies on auto-complete functionality. To begin, I installed some available templates using the dotnet command line tool and then selected a template directory before installing the Angular template. dotnet ne ...

How can I use React to create a dictionary that modifies several values depending on a single property?

I am looking for a more efficient way to handle the following code in my component example. I have a list component that can display different types of animals such as dogs, cats, and bunnies with specific visual changes and functionality from the API. exp ...

Tips on incorporating esbuild extensions in the template.yaml file of AWS SAM

Currently, my TypeScript Lambda functions are managed using the AWS Serverless Application Model (SAM), and I rely on esbuild for the build process. I'm interested in incorporating esbuild plugins into my build process to enable support for TypeScrip ...

Compilation error in VueJS: missing dependency detected

I am facing an issue in my VueJS project where a file I am referencing seems to be causing a compilation error. Despite being present in the node_modules directory, the dependency is declared as not found. In the image on the left, you can see the directo ...

Tips for ensuring session token verification remains intact upon reloading

I am currently in the process of developing a website using the Next.js framework and I am seeking advice on how to prevent the reload effect that occurs when transitioning from the login page back to the main page for just a fraction of a second. Below i ...

Is it feasible for the Drawer to be a fixed feature that sits atop the content?

I am looking to have a compact drawer positioned on the left side of my screen, similar to the example shown in the Material UI Documentation: https://i.sstatic.net/W21Kd.png However, I would like it to float over the content (like the variant="temporary ...

Is it possible to simultaneously update two entities using a single endpoint?

In order to update data in two different entities with a @OneToOne relationship between UserEntity and DetailsEntity, I need to create a function in my service that interacts with the database. Here are the entity definitions: UserEntity @Entity() export ...

Tips for accessing the 'index' variable in *ngFor directive and making modifications (restriction on deleting only one item at a time from a list)

Here is the code snippet I'm working with: HTML: <ion-item-sliding *ngFor="let object of objectList; let idx = index"> <ion-item> <ion-input type="text" text-left [(ngModel)]="objectList[idx].name" placeholder="Nam ...

Using ts-jest for mocking internal modules

Within my .ts module, I have the following code: import client from './client'; export default class DefaultRequest implements IRequest { make(req: Request): Promise<Response> { return new Promise<Response>((resolve, reje ...

Error message "The process is not defined during the Cypress in Angular with Cucumber process."

Exploring Cypress for end-to-end testing in an Angular 12 project with Cucumber and TypeScript has been quite the journey. Cypress launches successfully using npx cypress open, displaying the feature file I've created: https://i.sstatic.net/Q5ld8.png ...

`Incredible sequence of events unfolding`

In order to add an additional action after the deletion process is complete, I must make modifications to an epic. The current epic code is as follows: const deleteComponentEpic: Epic< AppActions, AppActions, AppStore, ComponentDetailsEpicsDepen ...

Implementing custom query filtering in apollo-server-express

Most of the requests and changes processed by my server require authorization. But, there are a few specific resolvers that need to be public such as sign-in, register, and forgot-password. How can I enable these resolvers to be accessed selectively and au ...

Conceal a specific segment on the web page if the API call in Angular does not return any data

I'm currently working with data retrieved through an API call and I need assistance in implementing code to hide a section when there is no data being fetched. Could you provide a sample code for this? ...

When a new array object is added to a nested array in a React Redux reducer, the array in the store is correctly updated but the React component

I am brand new to React and redux. Currently, I have a task where I need to implement workflows with tasks inside them. While I successfully managed to add a new workflow object to the state array, I encountered a problem when trying to add a new task - it ...

Exploring the method to retrieve a dynamically added property in Typescript

My React Component Loader receives certain props. The contentAlign property is only available when the local property exists and its value is 'relative'. I am encountering an error when trying to include contentAlign in the props, and I cannot ...

Error in Ionic 3: "this is null"

Whenever I fetch data from Firebase, I am attempting to redirect accordingly. If the data is null or empty, then there is no need for redirection. My attempt involves using this.navCtrl.push(ProspectPage); but for some reason, it is not functioning proper ...