From 55f2c0cb49d18ac7f985c23a98cb600f77e7e5a4 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Mon, 1 Aug 2022 17:19:15 -0400 Subject: [PATCH] No synthetic Awaited for unconstrained type when not a type variable (#50100) --- src/compiler/checker.ts | 6 ++-- .../reference/awaitedType.errors.txt | 10 ++++++ tests/baselines/reference/awaitedType.js | 14 +++++++++ tests/baselines/reference/awaitedType.symbols | 31 +++++++++++++++++++ tests/baselines/reference/awaitedType.types | 25 +++++++++++++++ tests/cases/compiler/awaitedType.ts | 10 ++++++ 6 files changed, 94 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index cd2254c87b8..7ac4bb7d5a5 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -36710,9 +36710,11 @@ namespace ts { // We only need `Awaited` if `T` contains possibly non-primitive types. if (isGenericObjectType(type)) { const baseConstraint = getBaseConstraintOfType(type); - // We only need `Awaited` if `T` has no base constraint, or the base constraint of `T` is `any`, `unknown`, `{}`, `object`, + // We only need `Awaited` if `T` is a type variable that has no base constraint, or the base constraint of `T` is `any`, `unknown`, `{}`, `object`, // or is promise-like. - if (!baseConstraint || (baseConstraint.flags & TypeFlags.AnyOrUnknown) || isEmptyObjectType(baseConstraint) || isThenableType(baseConstraint)) { + if (baseConstraint ? + baseConstraint.flags & TypeFlags.AnyOrUnknown || isEmptyObjectType(baseConstraint) || isThenableType(baseConstraint) : + maybeTypeOfKind(type, TypeFlags.TypeVariable)) { return true; } } diff --git a/tests/baselines/reference/awaitedType.errors.txt b/tests/baselines/reference/awaitedType.errors.txt index e5918016fc7..b829b3f22e7 100644 --- a/tests/baselines/reference/awaitedType.errors.txt +++ b/tests/baselines/reference/awaitedType.errors.txt @@ -177,4 +177,14 @@ tests/cases/compiler/awaitedType.ts(22,12): error TS2589: Type instantiation is async function f17_usage() { const x = await f17(async () => 123 as const); return { x }; + } + + // https://github.com/microsoft/TypeScript/issues/47144 + type GenericStructure< + AcceptableKeyType extends string = string + > = Record; + + async function brokenExample(structurePromise: Promise>, key: AcceptableKeyType): Promise { + const structure = await structurePromise; + structure[key] = 1; } \ No newline at end of file diff --git a/tests/baselines/reference/awaitedType.js b/tests/baselines/reference/awaitedType.js index 5f4937e3ff1..3cdacff404e 100644 --- a/tests/baselines/reference/awaitedType.js +++ b/tests/baselines/reference/awaitedType.js @@ -169,6 +169,16 @@ async function f17 Promise>(fn: T) { async function f17_usage() { const x = await f17(async () => 123 as const); return { x }; +} + +// https://github.com/microsoft/TypeScript/issues/47144 +type GenericStructure< + AcceptableKeyType extends string = string +> = Record; + +async function brokenExample(structurePromise: Promise>, key: AcceptableKeyType): Promise { + const structure = await structurePromise; + structure[key] = 1; } //// [awaitedType.js] @@ -281,3 +291,7 @@ async function f17_usage() { const x = await f17(async () => 123); return { x }; } +async function brokenExample(structurePromise, key) { + const structure = await structurePromise; + structure[key] = 1; +} diff --git a/tests/baselines/reference/awaitedType.symbols b/tests/baselines/reference/awaitedType.symbols index c6b338d5d70..2f8d493332e 100644 --- a/tests/baselines/reference/awaitedType.symbols +++ b/tests/baselines/reference/awaitedType.symbols @@ -433,3 +433,34 @@ async function f17_usage() { return { x }; >x : Symbol(x, Decl(awaitedType.ts, 169, 12)) } + +// https://github.com/microsoft/TypeScript/issues/47144 +type GenericStructure< +>GenericStructure : Symbol(GenericStructure, Decl(awaitedType.ts, 170, 1)) + + AcceptableKeyType extends string = string +>AcceptableKeyType : Symbol(AcceptableKeyType, Decl(awaitedType.ts, 173, 22)) + +> = Record; +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>AcceptableKeyType : Symbol(AcceptableKeyType, Decl(awaitedType.ts, 173, 22)) + +async function brokenExample(structurePromise: Promise>, key: AcceptableKeyType): Promise { +>brokenExample : Symbol(brokenExample, Decl(awaitedType.ts, 175, 38)) +>AcceptableKeyType : Symbol(AcceptableKeyType, Decl(awaitedType.ts, 177, 29)) +>structurePromise : Symbol(structurePromise, Decl(awaitedType.ts, 177, 72)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --)) +>GenericStructure : Symbol(GenericStructure, Decl(awaitedType.ts, 170, 1)) +>AcceptableKeyType : Symbol(AcceptableKeyType, Decl(awaitedType.ts, 177, 29)) +>key : Symbol(key, Decl(awaitedType.ts, 177, 135)) +>AcceptableKeyType : Symbol(AcceptableKeyType, Decl(awaitedType.ts, 177, 29)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --)) + + const structure = await structurePromise; +>structure : Symbol(structure, Decl(awaitedType.ts, 178, 7)) +>structurePromise : Symbol(structurePromise, Decl(awaitedType.ts, 177, 72)) + + structure[key] = 1; +>structure : Symbol(structure, Decl(awaitedType.ts, 178, 7)) +>key : Symbol(key, Decl(awaitedType.ts, 177, 135)) +} diff --git a/tests/baselines/reference/awaitedType.types b/tests/baselines/reference/awaitedType.types index 8729e64ce84..f7747e2a697 100644 --- a/tests/baselines/reference/awaitedType.types +++ b/tests/baselines/reference/awaitedType.types @@ -392,3 +392,28 @@ async function f17_usage() { >{ x } : { x: 123; } >x : 123 } + +// https://github.com/microsoft/TypeScript/issues/47144 +type GenericStructure< +>GenericStructure : GenericStructure + + AcceptableKeyType extends string = string +> = Record; + +async function brokenExample(structurePromise: Promise>, key: AcceptableKeyType): Promise { +>brokenExample : (structurePromise: Promise>, key: AcceptableKeyType) => Promise +>structurePromise : Promise> +>key : AcceptableKeyType + + const structure = await structurePromise; +>structure : GenericStructure +>await structurePromise : GenericStructure +>structurePromise : Promise> + + structure[key] = 1; +>structure[key] = 1 : 1 +>structure[key] : GenericStructure[AcceptableKeyType] +>structure : GenericStructure +>key : AcceptableKeyType +>1 : 1 +} diff --git a/tests/cases/compiler/awaitedType.ts b/tests/cases/compiler/awaitedType.ts index 9a965141d9a..0a64eed5d31 100644 --- a/tests/cases/compiler/awaitedType.ts +++ b/tests/cases/compiler/awaitedType.ts @@ -171,4 +171,14 @@ async function f17 Promise>(fn: T) { async function f17_usage() { const x = await f17(async () => 123 as const); return { x }; +} + +// https://github.com/microsoft/TypeScript/issues/47144 +type GenericStructure< + AcceptableKeyType extends string = string +> = Record; + +async function brokenExample(structurePromise: Promise>, key: AcceptableKeyType): Promise { + const structure = await structurePromise; + structure[key] = 1; } \ No newline at end of file