Why doesn't TypeScript automatically determine the prop type when Generics are used?

Below is the code snippet:

interface MyInterface {
   a: {
     b: {
       c: "c";
    };
  };
}

type ParentProps = keyof MyInterface
type ChildProps<ParentProp extends ParentProps> = keyof MyInterface[ParentProp]

type GrandChildType<ParentProp extends ParentProps, ChildProp extends ChildProps<ParentProp>> =
  MyInterface[ParentProp][ChildProp]['c']

An error occurs in the GrandChildType section:

The type '"c"' cannot be used to index type 'MyInterface[ParentProp][ChildProp]'.(2536)

However, when the last line is altered to:

type GrandChildType<ParentProp extends ParentProps, ChildProp extends ChildProps<ParentProp>> =
  MyInterface[ParentProp][ChildProp]

type test = GrandChildType<'a', 'b'>['c']

The correct type of c, which is "c", is obtained. So, the question arises: why is it not possible to retrieve that value type using Generics if both ParentProps and ChildProps are keys extracted from MyInterface?

Reproducible link: typescript playground

Answer №1

It appears there is an issue in TypeScript that affects nested generic indexed access types, causing them to lose their constraint when trying to index into them with a specific key. This bug has been reported on GitHub for some time now without any indication of it being fixed soon, so it may be necessary to find a workaround.

If you encounter a scenario where you know a type T extends another type U, but the compiler does not recognize this fact, you can consider using the Extract<T, U> utility type as a potential solution. By replacing T with Extract<T, U>, you are likely to satisfy the compiler's expectations and resolve any issues arising from the incorrect recognition of type extensions.

To successfully index into a type T with the key type "c", it should be possible to assign the type to {c?: any}. If attempting to access

T["c"]</code results in an error, using <code>Extract<T , {c?: any}>
might offer a viable alternative. Try it out:

type GrandChildType<K extends keyof MyInterface, K2 extends keyof MyInterface[K]> = Extract<MyInterface[K][K2], { c?: any }>['c']; // works fine

type C = GrandChildType<"a", "b"> // returns "c"

Great! The type of GrandChildType<"a", "b"> is indeed "c", resolving any issues encountered within the GrandChildType definition.

Access Playground link here

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

Tips for adding temporary text in filter input of Kendo UI Grid using Angular

I'm currently working with Kendo UI Grid in conjunction with Angular, and I am struggling to find a solution for adding text or a placeholder in filter inputs using Typescript. Within my code, I am utilizing the kendoGridFilterCellTemplate: <kend ...

What is the best method for distributing an Angular service from a library created using ng generate library?

I'm currently facing a challenge in sharing a service from the npm package that I created using ng g library with my Angular hosting application. While I have experience in linking components and directives, I'm a bit lost when it comes to servic ...

Typescript MUI Autocomplete: Can you specify the parameter type of the PaperComponents function?

If you use MUI's Autocomplete, there is a property called PaperCompomponent that allows you to pass your own react component. This property is a function with properties as a parameter, which can then be used to pass on to your custom component. In T ...

Tips for designing a custom TypeScript 5 property decorator

I have a decorator in TypeScript: const bindMethod = (method: any): PropertyDecorator => ((target: any, name?: PropertyKey): any => { if(name === undefined) { throw new Error('Bound decorator must be used with a property name.& ...

Embedding images using a blob or base64 format does not function properly on iOS devices

I'm facing an issue with setting the src of an img tag to display an image. The code snippet below works fine on android, mac, and windows, but it is not functioning correctly on iOS: let base64Image = pageModel.image; this.$currentPageImage.src = `da ...

Is it possible to utilize both $uibModal and $uibModalInstance within the same controller to create a modal popup in an Angular project incorporating TypeScript?

Being new to Angular with Typescript, I encountered an issue while trying to implement a modal popup in Angular. The problem arises when I have a dropdown menu that triggers the opening of a modal popup with two buttons, "Yes" and "No". To handle this, I h ...

Using Angular to Bind Checkbox Value in Typescript

I have a challenge of creating a quiz where a card is displayed with 4 questions structured like this: <div class="col-md-6"> <div class="option" id="Answer1"> <label class="Answer1"> <input value= "Answer1" type="checkbox ...

What is the best way to incorporate an interface in TypeScript that is both callable and has properties?

Given the scenario where an interface is defined as: interface FooWithBar { ():void; bar():void; } I am struggling with writing the implementation. I attempted the following: function foo(){ } foo.bar = function(){ }; This approach did not wo ...

Inheriting static attributes in Typescript without using the static keyword

My project involves utilizing multiple classes that represent entities from a database. abstract class Entity { static columns: Column[]; static showInNav: boolean; static dependencies: string[]; // non-static fields } class Entity_A exten ...

Component unit testing in Angular 2/4 fails to register click events causing a lack of change detection

I'm currently working on testing a component in Angular 2/4 to determine if clicking on a button element will result in the desired changes. However, I'm facing an issue with triggering the click event. Here is the component code: import { Comp ...

Issue: The keyword in React/React-Native is returning a boolean value instead of the expected element object

I've recently delved into learning and coding with React, and I'm encountering a bug that I need help fixing. The issue lies within my application screen where I have two checkboxes that should function like radio buttons. This means that when on ...

filter failing to provide output

Issue with fetching partnername from the filter function, always returning undefined. administrationList = [ { "runid": 6, "partnerid": 2, "partnername": "test admin2", }, { "runid& ...

Is it feasible to link an Angular property value to the value of an HTML data attribute?

Can an Angular property value be bound to a data attribute on a template element? <h1 data-name="{{name}}">Hello from {{ name }}!</h1> Example Link After running the code, it results in the following error: Error in src/main.ts (11: ...

The error message "better-sqlite3 TypeError: o.default is not a constructor" indicates that

As part of my vscode extension development in typescript, webpack, and better-sqlite3, I am attempting to create a database within the C:\Users\userName\AppData\Roaming\Code\User\globalStorage\ folder. However, when ...

Tips for navigating to a specific row within a designated page using the Angular Material table

Utilizing angular material, I have set up a table with pagination for displaying data. When a user clicks on a row, they are redirected to another page. To return to the table page, they must click on a button. The issue arises when the user needs to retu ...

What is the best way to determine which option is most suitable: types, classes, or function types in TypeScript for

Currently, I am developing a small todo command line utility with a straightforward program structure. The main file is responsible for parsing the command line arguments and executing actions such as adding or deleting tasks based on the input provided. E ...

Incorporating onPause and onResume functionalities into a YouTube video featured on a page built with Ionic 2

I'm encountering a minor problem with a simple demo Android app built in Ionic 2. Whenever a Youtube video is playing on the Homepage, if the power button is pressed or the phone goes into sleep/lock mode, the Youtube video continues to play. This is ...

Tips for showcasing unique validation error messages

My form includes a text area for the user to input JSON Code. If the entered text is not valid JSON, an error message should be displayed but unfortunately, it's not working as expected. Below is my custom validator code: import { AbstractControl, V ...

Unable to retrieve dynamically generated object property from an array in AngularJS 2+

Here is an example of an items array: this.itemList = [ { id: 1, name: 'a', address: 'as dasf a' }, { id: 2, name: 'b', address: 'as dasf a' }, { id: 3, name: 'c', address: 'as dasf a' } ]; ...

Clicking on the image in Angular does not result in the comments being displayed as expected

I find it incredibly frustrating that the code snippet below is not working as intended. This particular piece of code was directly copied and pasted from an online Angular course I am currently taking. The objective of this code is to display a card view ...