Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nested mapped types are inferred to be any #23918

Closed
steffenvv opened this issue May 5, 2018 · 6 comments
Closed

Nested mapped types are inferred to be any #23918

steffenvv opened this issue May 5, 2018 · 6 comments
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed

Comments

@steffenvv
Copy link

I'm trying to have the compiler infer the type of a deeply nested object, while transforming the type with a mapped type at every level of nesting. But the inferred type seems to be resolved to any at a certain depth.

TypeScript Version: 2.9.0-dev.20180503

Search Terms:

Infer
Nested
Mapped type
Any

Code

export interface Mapper<T> {
    map(value: T): T;
}

export type Mappers<T> = { [K in keyof T]: Mapper<T[K]> };

declare const stringMapper: Mapper<string>;

declare function combineMappers<T>(mappers: Mappers<T>): Mapper<T>;

export const t1 = combineMappers({
    a: stringMapper,
    b: stringMapper
});

export const t2 = combineMappers({
    c: t1
});

export type T1 = ReturnType<typeof t1.map>;
/* T1 = { a: string; b: string }
   
   as desired */

export type T2 = ReturnType<typeof t2.map>;
/* T2 = { c: { a: any; b: any } }
   
   but I would like it to be

        { c: { a: string; b: string } } */

export type T3 = { [K in keyof T2]: T2[K] };
/* T3 = { c: { a: string; b: string } }
   
   according to VS code tooltip, but in the corresponding
   tooltip in the .d.ts output, it still says any */

Expected behavior:

I want the compiler to be able to infer a deeply nested mapped type.

Actual behavior:

The inferred type seems to be resolved to any at a certain depth. Sometimes, the VS code tooltips gives the correct type while the emitted .d.ts file does not.

Playground Link: link

Related Issues: Possibly #22715

@ahejlsberg
Copy link
Member

The compiler is actually inferring the right type, but when producing the text representation of the type (e.g. for tool tips or declaration file emit) it stops after observing multiple levels of nesting of the same type in order to avoid what might be an infinitely nested type. It is a known design limitation. See also #23433.

@ahejlsberg ahejlsberg added the Design Limitation Constraints of the existing architecture prevent this from being fixed label May 5, 2018
@steffenvv
Copy link
Author

I see! Thank you for the quick and enlightening response!

Do you have any ideas for workarounds to achieve the desired .d.ts output? In my real application I would really like to be able to export these types across package boundaries.

Would it be possible to work around the issue by adding some "uniqueness" at each level? What exactly triggers the suspicion that the type is infinitely recursive? Is it sufficient to encounter any parametrization of Mapper in the above example, or would it help to add another type parameter that's different at each level? (Not really sure how to achieve that, in any case...)

Alternatively, can we improve the type-to-text algorithm to "tolerate" potential recursion until it reaches a certain maximum depth? If you point me at the relevant code, I would be very willing to give it a shot.

@steffenvv
Copy link
Author

Another thought/question. If the compiler succeeds in inferring a type from an initializer, will it then be definitely possible to display the type without endless recursion? If so, could we add a flag to the type to remember that it's safe to display? Or does "possible to infer" not imply "possible to display"? I feel like I might be missing some distinction here.

@typescript-bot
Copy link
Collaborator

Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.

@AlexGalays
Copy link

Is there a workaround to help the text representation be useful then?

@luxalpa
Copy link

luxalpa commented Sep 20, 2018

This is NOT just text representation. It really allows you to set anything in that type without throwing any kind of errors. Very problematic and unsafe.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed
Projects
None yet
Development

No branches or pull requests

5 participants