Skip to content

Removing optional modifier in homomorphic mapped types does not work in generic contexts since 5.5.x #59902

@Fullfungo

Description

@Fullfungo

🔎 Search Terms

optional modifier, required fields, generic, NonNullable, strictNullChecks, homomorphic mapped types

🕗 Version & Regression Information

  • This changed between versions 5.4.5 and 5.5.2
  • This changed in commit or PR e418f8d (as reported by every-ts)

⏯ Playground Link

https://www.typescriptlang.org/play/?ts=5.5.4#code/MYewdgzgLgBApgDwIYFsAOAbOMC8MA8AKvAlHGACYQzQBOAlmAOYB8AFAJQBcMSYAnrhYwA3gCgYMAPRSYAJTiYkwRkxgB3elAAWvATTRwVAM3rAaAVwBGAWij9DMEMZgADOqtcwUSANZxqHWx7Q2pQWlojWCQmJEYAOglpWRDsYjwPZgBuMSTUmABlEBQ4AHk0KHpwJAxcURgAbX9BRhhCAF0Afh4ARhgAXxzJPIdsAEEMDAUARwt6SIo6kUbmmFbm50LisoqqsBr2m26YPsHcyXyZuYWANRqLALqJqbhZ+bgKJrh+Teer94o7RySRkMAAwsUlIxqK0AKzxAAs8QQABoYFYLLBTGBsHD4vCEElQJBYAgeP9bvdHngLJQ4NiPucYJEoBZaGAYAgcoMgA

💻 Code

const example = <T extends string>(): any => {
  // Replacing with any specific sub-type of `string` makes the types correct again.
  // type T = string;

  type SomeOptional = { [key in T]?: 1 };
  
  type AllRequired = { [key in keyof SomeOptional]-?: 1 };

  type RequiredValues = AllRequired[keyof AllRequired];

  // Complains in 5.4.x, but fine in 5.5.x
  const x: RequiredValues = undefined

  return x;
};

🙁 Actual behavior

Using -? leaves the fields marked as optional, and taking the values of the resulting type gives a union with undefined.

🙂 Expected behavior

Using -? makes all fields required, and taking the values of the resulting type gives a union of field types.

Additional information about the issue

Requires a --strictNullChecks flag.

Replacing keyof SomeOptional with NonNullable<keyof SomeOptional> or keyof SomeOptional as keyof SomeOptional fixes the issue. It looks like this problem is limited to homomorphic mapped types.

Using Required<{ [P in keyof SomeOptional]: 1; }> in place of { [key in keyof SomeOptional]-?: 1 } results in the same behaviour.

Metadata

Metadata

Assignees

Labels

BugA bug in TypeScriptDomain: Mapped TypesThe issue relates to mapped typesFix AvailableA PR has been opened for this issue

Type

No type
No fields configured for issues without a type.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions