Utilizing inferred function parameter type to narrow down the type selection for indexing another type

Trying to understand why narrowing the type of the parentEntityMetas is not working as expected.

The goal is to narrow it down based on the parentEntityType passed to the function.

I attempted to extract the correct parentEntityMetas type from the SettingsParentEntityTypeMetas using the inferred parentEntityType as an index in the type.

Expecting the condition set on parentEntityType to narrow the type, but it seems to not be working.

Any help or hints would be greatly appreciated.

export type SettingsParentEntityType =
  | 'Workspace'
  | 'Artist';

export type SettingsParentEntityTypeMetas = {
  Workspace: {
    workspaceId: string;
  };
  Artist: {
    releaseId: string;
  };
};

type Params<
  T extends SettingsParentEntityType
> = {
  parentEntityType: T;
  parentEntityMetas?: SettingsParentEntityTypeMetas[T];
};

const editor = <
  T extends SettingsParentEntityType
>({
  parentEntityType,
  parentEntityMetas,
}: Params<T>) => {
    const releaseId =  parentEntityType === 'Artist' && parentEntityMetas && parentEntityMetas.releaseId; 
}

TS reports an error when attempting to access parentEntityMetas.releaseId.

Try running the code on TypeScript Playground for more insights: TypeScript Playground

Answer №1

To achieve the desired behavior, I made slight modifications to your types:

export type SettingsParentEntityTypeMetas = {
  Workspace: {
    type: 'workspace',
    workspaceId: string;
  };
  Artist: {
    type: 'artist'
    releaseId: string;
  };
};

export type SettingsParentEntityType = keyof SettingsParentEntityTypeMetas

type Values<T> = T[keyof T]

type Params = {
  [P in SettingsParentEntityType]: {
    parentEntityType: P;
    parentEntityMetas?: SettingsParentEntityTypeMetas[P];
  }
};

const editor = ({
  parentEntityType,
  parentEntityMetas,
}: Values<Params>) => {
  if (parentEntityMetas) {
    if (parentEntityMetas.type === 'workspace') {
      parentEntityMetas.workspaceId // ok
    }
  }
}

Playground

export type SettingsParentEntityTypeMetas = {
  Workspace: {
    workspaceId: string;
  };
  Artist: {
    releaseId: string;
  };
};

export type SettingsParentEntityType = keyof SettingsParentEntityTypeMetas

type Params = {
  [P in SettingsParentEntityType]: {
    parentEntityType: P;
    parentEntityMetas?: SettingsParentEntityTypeMetas[P];
  }
};

const editor = <P extends SettingsParentEntityType, M extends Params>(
  parentEntityType:P,
  parentEntityMetas:M[P],
) => {

}
editor('Workspace', )

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

Starting up the Angular 2 Bootstrap Datepicker

For my Angular 2 application, I am using the Bootstrap datepicker plugin () but encountering some initialization issues. The code snippet below is currently working for initializing the datepicker in my component, however, it does not look very clean: ng ...

"Exploring the world of 3rd party libraries in Angular2 with Typescript and Webpack

I've begun working on a fantastic seed project that can be found at: https://github.com/AngularClass/angular2-webpack-starter However, I've encountered an issue with integrating third-party modules. Can anyone offer guidance on how to properly a ...

JEST is throwing an error stating that the import statement cannot be used outside of a module in a React app created using Create React App with TypeScript. I have tried to find a solution for this

Despite reading numerous possible solutions, none seem to work in my case (my configuration files are now overflowing). The issue arises on this line: import axios from "axios"; Below are my configuration files: //jest.config.ts import type { Config } fro ...

There is no component factory available for the DialogDataExampleDialog. Have you ensured to include it in the @NgModule entryComponents?

Currently, I am a beginner in Angular. I recently started integrating MatDialog into my project. To do this, I followed the code provided on the official Angular documentation page https://material.angular.io/components/dialog/overview. However, upon click ...

Avoid navigating to the subscribe block when the server sends a response in Angular

When trying to send a request to the server and check the response, I am not seeing any results. The code for sending the request is below: SendVerificationInfo(item: SendVerificationModel): Observable < any > { return this.httpClient.post < any ...

What is the correct way to utilize environment variables in TypeScript?

I am currently working on creating a basic API using TypeScript. However, I have encountered an issue where whenever I utilize an environment variable, the TS compiler throws an error indicating that it could be undefined. For example: // Not Working con ...

Retrieve data upon component mounting and deactivate the query in React-query

When navigating to a search result page, query parameters are passed to useQuery. I want the data to be fetched only when the user clicks the "Search" button after changing the search prompt. I attempted to use enabled: false and call refetch() on button ...

Mapping the properties of a Zod Discriminated Union: A step-by-step guide

Suppose we have a discriminated union export const duParser = z.discriminatedUnion('type', [ z.object({ type: z.literal('a'), id: aParser, }), z.object({ type: z.literal('b'), id: bParser, }), ]); The ...

What is the process for updating the text and destination of a navigation button?

I have a navigation bar element with a button that redirects me to the path "/NEXUM" using React-Router. However, once I am on the NEXUM page, I want the text and destination of the navigation bar to change so that clicking it will take me to another path ...

What are the benefits and drawbacks of utilizing two distinct methods to regulate a component in Vue?

I've developed two components that display "on" or "off" text, along with a button that toggles the state of both components. Here is the link to the codesandbox for reference: https://codesandbox.io/s/serene-mclean-1hychc?file=/src/views/Home.vue A ...

New Entry failing to appear in table after new record is inserted in CRUD Angular application

Working with Angular 13, I developed a basic CRUD application for managing employee data. Upon submitting new information, the createEmployee() service is executed and the data is displayed in the console. However, sometimes the newly created entry does no ...

Configuring NextJs routes with multiple parameters

Seeking guidance on structuring files in Nextjs for handling multiple URL parameters. Can anyone offer advice? The given URL structure is: /api/upload?file=${filename}&fileType=${fileType} This is the current file structure: app api upload ...

How can we limit the CSS properties that can be used in an interpolated manner by defining a restricted TS type for CSS props based on emotions?

When dealing with emotions, how can we specify a restricted TS type for the css prop to only allow certain css properties to be interpolated? For instance, consider the following scenario: // This is considered valid css = {{ color: 'white', ...

The default sanitizer of Express-validator fails to function properly when it is linked with other sanitizers

I am encountering an issue with the default() sanitizer from express-validator. It seems that when I include it in a chain, like this: body("children").optional().isArray().default([]), the default function does not have any effect, leading to ch ...

Ways to activate a click event on a parent div without affecting a particular child element in Angular

I am working on an Angular component that consists of nested div elements. My goal is to trigger a click event on the parent div, however, I want to ensure that if the menu child div is clicked, the parent div's click event should not be triggered. C ...

What is the purpose of type casting in Typescript?

As a TS newcomer, I have a question that surprisingly lacks a clear explanation. What is the main difference between specifying the type to TypeScript in these two ways: const ul = document.querySelector('#nav') as HTMLUListElement; and this way ...

Why has the need to import toPromise in Angular/rxjs vanished?

Many responses on Stack Overflow mention that to prevent issues like Error message: Property 'toPromise' does not exist on type 'Observable' in Angular, you are advised to import 'rxjs/add/operator/toPromise'. I followed t ...

Having trouble with debugging in Visual Studio for TypeScript (specifically Angular) projects? If Visual Studio 2017 is skipping over your breakpoints

// ============================== see updates below ============================== // While attempting to debug a TypeScript application in Visual Studio 2017 (NOT Visual Studio Code), I encountered an issue where inserting a breakpoint on a .ts file resu ...

Sending chosen selection in a scrollable dropdown menu in Angular

Here is the HTML code that I'm working with: <div class="container"> <div> <h1 class="table-title">Employees</h1> <table class="table"> <thead class="thead-dark"& ...

NestJS Error TS2339: The property "buffer" is not found on the type File

Within my NestJs application, I have a file being returned from a controller endpoint with the following structure: const file = { fieldname: "file", originalname: "filename.png", encoding: "7bit", mimetype: "imag ...