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

Awaited<T> not resolved to T when T is a generic type #47144

Closed
frank-weindel opened this issue Dec 14, 2021 · 6 comments · Fixed by #50100
Closed

Awaited<T> not resolved to T when T is a generic type #47144

frank-weindel opened this issue Dec 14, 2021 · 6 comments · Fixed by #50100
Assignees
Labels
Fix Available A PR has been opened for this issue Needs Investigation This issue needs a team member to investigate its status. Rescheduled This issue was previously scheduled to an earlier milestone

Comments

@frank-weindel
Copy link

frank-weindel commented Dec 14, 2021

Bug Report

I thought this issue might be related to #46543, but that issue seems to apply to ALL ts versions. This issue is a regression between 4.4.4 and 4.5. In addition to reporting this bug I offer a very simple workaround.

🔎 Search Terms

generic, index, indexed record, type resolution, promise, awaited, workaround

🕗 Version & Regression Information

  • This changed between versions 4.4.4 and 4.5
  • Edit (3/7/22): Still an issue in 4.5.5 and 4.6.2

Bug started in 4.5 release.

Not fixed in the nightly version as of December 14th 7am ET.

⏯ Playground Link

The example below is purposely contrived in order to express the issue in simple terms.

Playground link with relevant code

💻 Code

export type GenericStructure<
  AcceptableKeyType extends string = string
> = Record<AcceptableKeyType, number>;

/**
 * structure[key] assignment compiles prior to 4.5, but fails in 4.5.3
 */
async function brokenExample<AcceptableKeyType extends string = string>(structurePromise: Promise<GenericStructure<AcceptableKeyType>>, key: AcceptableKeyType): Promise<void> {
  const structure = await structurePromise;
  structure[key] = 1;
}

/**
 * Possible workaround by explicit typing of 'structure'
 */
async function workAroundExample<AcceptableKeyType extends string = string>(structurePromise: Promise<GenericStructure<AcceptableKeyType>>, key: AcceptableKeyType): Promise<void> {
  const structure: GenericStructure<AcceptableKeyType> = await structurePromise;
  structure[key] = 1;
}

🙁 Actual behavior

In brokenExample():

The type of const structure is implicitly resolved to Awaited<GenericStructure<AcceptableKeyType>>

Assignment of structure[key] = 1; results in this error:

Type 'number' is not assignable to type 'Awaited<GenericStructure<AcceptableKeyType>>[AcceptableKeyType]'.(2322)

🙂 Expected behavior

In brokenExample():

The type of const structure should be implicitly resolved to GenericStructure<AcceptableKeyType>

Assignment of structure[key] = 1; should not result in an error.

@RyanCavanaugh RyanCavanaugh added the Needs Investigation This issue needs a team member to investigate its status. label Dec 14, 2021
@RyanCavanaugh RyanCavanaugh added this to the TypeScript 4.6.0 milestone Dec 14, 2021
@NtsDK
Copy link

NtsDK commented Jan 5, 2022

Got the same problem. Workaround works, thank you)

@connor4312
Copy link
Member

connor4312 commented Jan 20, 2022

I believe I ran into a similar issue in VS Code. On 4.6.0 nightly, this is broken:

async function filterDefined<T>(arr: Promise<T | undefined>[]): Promise<T[]> {
    const r = await Promise.all(arr);
    return r.filter((r): r is T => r !== undefined);
}

But adding a type annotation makes it work:

async function filterDefined<T>(arr: Promise<T | undefined>[]): Promise<T[]> {
    const r: (T | undefined)[] = await Promise.all(arr);
    return r.filter((r): r is T => r !== undefined);
}

@jctaoo
Copy link

jctaoo commented Feb 8, 2022

I also ran into a similar issue:

class Test<Model> {
  constructor(private model: Model) {
  }
  
  async getObj(): Promise<Partial<Model>> { 
    return this.model;
  }
  
  async getKey<Key extends keyof Model>(obj: Model, key: Key): Promise<Model[keyof Model] | undefined> {
    const model = await this.getObj();
    // error: Type 'Awaited<Partial<Model>>[Key]' is not assignable to type 'Model[keyof Model] | undefined'.
    return model[key];
  }
}

But when I removed Partial, it will works will.

Typescript Playground

@frank-weindel
Copy link
Author

Verified that this is still an issue in 4.6.2.

Playground

@RyanCavanaugh RyanCavanaugh added the Rescheduled This issue was previously scheduled to an earlier milestone label May 13, 2022
@frank-weindel
Copy link
Author

Verified that this is still an issue in 4.8.0-beta

Playground

@frank-weindel
Copy link
Author

Thanks @rbuckton!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Fix Available A PR has been opened for this issue Needs Investigation This issue needs a team member to investigate its status. Rescheduled This issue was previously scheduled to an earlier milestone
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants