Skip to content

Using alias in Mapped Types will not work with string literal type inferΒ #49238

@misuken-dw

Description

@misuken-dw

Bug Report

πŸ”Ž Search Terms

Function Generic Type Infer String Literal Mapped Type alias

πŸ•— Version & Regression Information

This is a bug in the 4.7.x version of TS.

⏯ Playground Link

Playground link with relevant code

πŸ’» Code

Using as in Mapped Types seems to cause the value to be incorrectly inferred in the Literal Type of the value.

declare function foo1<T extends { [P in keyof T as Capitalize<P & string>]: V }, V extends string>(a: T): T;
declare function foo2<T extends { [P in keyof T & string as Capitalize<P>]: V }, V extends string>(a: T): T;
declare function foo3<T extends { [P in keyof T]: V }, V extends string>(a: T): T;
declare function foo4<T extends { [P in Capitalize<keyof T & string>]: V }, V extends string>(a: T): T;

export const r1 = foo1({A: "a"}); // TS4.6 { A: "a"; } | TS4.7  { A: string; }
export const r2 = foo2({A: "a"}); // TS4.6 { A: "a"; } | TS4.7  any -> 'r2' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.(7022)
export const r3 = foo3({A: "a"}); // TS4.6 { A: "a"; } | TS4.7  { A: "a"; }
export const r4 = foo4({A: "a"}); // TS4.6 { A: "a"; } | TS4.7  { A: "a"; }

πŸ™ Actual behavior

declare function foo1<T extends { [P in keyof T as Capitalize<P & string>]: V }, V extends string>(a: T): T;
declare function foo2<T extends { [P in keyof T & string as Capitalize<P>]: V }, V extends string>(a: T): T;
declare function foo3<T extends { [P in keyof T]: V }, V extends string>(a: T): T;
declare function foo4<T extends { [P in Capitalize<keyof T & string>]: V }, V extends string>(a: T): T;

export const r1 = foo1({A: "a"}); // ❗ { A: string; }
export const r2 = foo2({A: "a"}); // ❗ any -> 'r2' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.(7022)
export const r3 = foo3({A: "a"}); // βœ… { A: "a"; }
export const r4 = foo4({A: "a"}); // βœ…  { A: "a"; }

πŸ™‚ Expected behavior

declare function foo1<T extends { [P in keyof T as Capitalize<P & string>]: V }, V extends string>(a: T): T;
declare function foo2<T extends { [P in keyof T & string as Capitalize<P>]: V }, V extends string>(a: T): T;
declare function foo3<T extends { [P in keyof T]: V }, V extends string>(a: T): T;
declare function foo4<T extends { [P in Capitalize<keyof T & string>]: V }, V extends string>(a: T): T;

export const r1 = foo1({A: "a"}); // βœ… { A: "a"; }
export const r2 = foo2({A: "a"}); // βœ… { A: "a"; }
export const r3 = foo3({A: "a"}); // βœ… { A: "a"; }
export const r4 = foo4({A: "a"}); // βœ… { A: "a"; }

Metadata

Metadata

Assignees

Labels

Working as IntendedThe behavior described is the intended behavior; this is not a bug

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions