Skip to content

Type 'keyof T' cannot be used to index type 'T extends <type>' with unions in v4.4.4 and newer #46495

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

Closed
Basssiiie opened this issue Oct 23, 2021 · 1 comment · Fixed by #46526
Assignees
Labels
Bug A bug in TypeScript Fix Available A PR has been opened for this issue

Comments

@Basssiiie
Copy link

Basssiiie commented Oct 23, 2021

Bug Report

🔎 Search Terms

  • Type cannot be used to index type
  • keyof union type index

This one was kinda hard to find search terms for, I mainly look at changes between v.4.3.5 and v.4.4.4 in the changelog and could not find anything that could have potentially caused this.

🕗 Version & Regression Information

This changed between versions v4.3.5 and v4.4.4. It works fine on TS Playground on v4.3.5 and earlier but errors on v4.4.4 and later.

⏯ Playground Link

Playground link with relevant code

💻 Code

Same as TS Playground link minus workaround comments:

interface Button 
{
  type: "button";
  text: string;
}

interface Checkbox 
{
  type: "checkbox";
  isChecked: boolean;
}

type Control = Button | Checkbox;

function update<T extends Control, K extends keyof T>(control : T | undefined, key: K, value: T[K]): void
{
  if (control !== undefined)
  {
    control[key] = value; // this breaks on v4.4.4 but works on v4.3.5
  }
}

🙁 Actual behavior

When running the code above in v4.4.4 and later versions it errors on the last line (control[key] = value;) with:

Type 'K' cannot be used to index type 'Control'.

When transpiling the code on v4.3.5 and earlier it works fine.

Both these two workarounds work on all versions:

(control)[key] = value; // add parentheses
const c = control; // use inline variable
c[key] = value;

It seems like control is resolved to type Control in the bugged snippet but resolves to T extends Control in the other snippets.

Also sidesnotes: the error goes away if | undefined is removed from the parameter type, and also if T is changed to something that is not an union.

🙂 Expected behavior

I would expect control would resolve to T extends Control in all 3 snippets of the code.

Thank you all for your time. :)

@Basssiiie Basssiiie changed the title Type 'keyof T' cannot be used to index type 'T extends <Class>' with unions in v4.4.4 and newer Type 'keyof T' cannot be used to index type 'T extends <type>' with unions in v4.4.4 and newer Oct 23, 2021
@ahejlsberg ahejlsberg self-assigned this Oct 25, 2021
@ahejlsberg ahejlsberg added the Bug A bug in TypeScript label Oct 25, 2021
@ahejlsberg ahejlsberg added this to the TypeScript 4.5.1 milestone Oct 25, 2021
@ahejlsberg
Copy link
Member

This is an effect of #43183 and the subsequent revision in #44621. The revision needs to be slightly less conservative. I'm surprised no one has run into this until now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Fix Available A PR has been opened for this issue
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants