mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Fix inference of type arguments when source is 'awaited'
This commit is contained in:
+30
-8
@@ -929,7 +929,7 @@ namespace ts {
|
||||
|
||||
let _jsxNamespace: __String;
|
||||
let _jsxFactoryEntity: EntityName | undefined;
|
||||
let outofbandVarianceMarkerHandler: ((onlyUnreliable: boolean) => void) | undefined;
|
||||
let outofbandVarianceMarkerHandler: ((variance: VarianceFlags) => void) | undefined;
|
||||
|
||||
const subtypeRelation = createMap<RelationComparisonResult>();
|
||||
const strictSubtypeRelation = createMap<RelationComparisonResult>();
|
||||
@@ -15797,6 +15797,9 @@ namespace ts {
|
||||
if (saved & RelationComparisonResult.ReportsUnreliable) {
|
||||
instantiateType(source, makeFunctionTypeMapper(reportUnreliableMarkers));
|
||||
}
|
||||
if (saved & RelationComparisonResult.ReportsAwaited) {
|
||||
instantiateType(source, makeFunctionTypeMapper(reportAwaitedMarkers));
|
||||
}
|
||||
}
|
||||
return entry & RelationComparisonResult.Succeeded ? Ternary.True : Ternary.False;
|
||||
}
|
||||
@@ -15831,10 +15834,12 @@ namespace ts {
|
||||
let propagatingVarianceFlags: RelationComparisonResult = 0;
|
||||
if (outofbandVarianceMarkerHandler) {
|
||||
originalHandler = outofbandVarianceMarkerHandler;
|
||||
outofbandVarianceMarkerHandler = onlyUnreliable => {
|
||||
outofbandVarianceMarkerHandler = variance => {
|
||||
propagatingVarianceFlags |=
|
||||
onlyUnreliable ? RelationComparisonResult.ReportsUnreliable : RelationComparisonResult.ReportsUnmeasurable;
|
||||
return originalHandler!(onlyUnreliable);
|
||||
variance === VarianceFlags.Awaited ? RelationComparisonResult.ReportsAwaited :
|
||||
variance === VarianceFlags.Unreliable ? RelationComparisonResult.ReportsUnreliable :
|
||||
RelationComparisonResult.ReportsUnmeasurable;
|
||||
return originalHandler!(variance);
|
||||
};
|
||||
}
|
||||
const result = expandingFlags !== ExpandingFlags.Both ? structuredTypeRelatedTo(source, target, reportErrors, intersectionState) : Ternary.Maybe;
|
||||
@@ -15966,7 +15971,7 @@ namespace ts {
|
||||
}
|
||||
else if (target.flags & TypeFlags.Awaited && source.flags & TypeFlags.Awaited) {
|
||||
const targetType = (<AwaitedType>target).awaitedType;
|
||||
const sourceType = instantiateType((<AwaitedType>source).awaitedType, makeFunctionTypeMapper(reportUnreliableMarkers));
|
||||
const sourceType = instantiateType((<AwaitedType>source).awaitedType, makeFunctionTypeMapper(reportAwaitedMarkers));
|
||||
// An `awaited S` is related to an `awaited T` if `S` is related to `T`:
|
||||
//
|
||||
// S <: T ⇒ awaited S <: awaited T
|
||||
@@ -16250,14 +16255,21 @@ namespace ts {
|
||||
|
||||
function reportUnmeasurableMarkers(p: TypeParameter) {
|
||||
if (outofbandVarianceMarkerHandler && (p === markerSuperType || p === markerSubType || p === markerOtherType)) {
|
||||
outofbandVarianceMarkerHandler(/*onlyUnreliable*/ false);
|
||||
outofbandVarianceMarkerHandler(VarianceFlags.Unmeasurable);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
function reportUnreliableMarkers(p: TypeParameter) {
|
||||
if (outofbandVarianceMarkerHandler && (p === markerSuperType || p === markerSubType || p === markerOtherType)) {
|
||||
outofbandVarianceMarkerHandler(/*onlyUnreliable*/ true);
|
||||
outofbandVarianceMarkerHandler(VarianceFlags.Unreliable);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
function reportAwaitedMarkers(p: TypeParameter) {
|
||||
if (outofbandVarianceMarkerHandler && (p === markerSuperType || p === markerSubType || p === markerOtherType)) {
|
||||
outofbandVarianceMarkerHandler(VarianceFlags.Awaited);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
@@ -16971,8 +16983,12 @@ namespace ts {
|
||||
for (const tp of typeParameters) {
|
||||
let unmeasurable = false;
|
||||
let unreliable = false;
|
||||
let awaited = false;
|
||||
const oldHandler = outofbandVarianceMarkerHandler;
|
||||
outofbandVarianceMarkerHandler = (onlyUnreliable) => onlyUnreliable ? unreliable = true : unmeasurable = true;
|
||||
outofbandVarianceMarkerHandler = (variance) =>
|
||||
variance === VarianceFlags.Awaited ? awaited = true :
|
||||
variance === VarianceFlags.Unreliable ? unreliable = true :
|
||||
unmeasurable = true;
|
||||
// We first compare instantiations where the type parameter is replaced with
|
||||
// marker types that have a known subtype relationship. From this we can infer
|
||||
// invariance, covariance, contravariance or bivariance.
|
||||
@@ -16994,6 +17010,9 @@ namespace ts {
|
||||
if (unreliable) {
|
||||
variance |= VarianceFlags.Unreliable;
|
||||
}
|
||||
if (awaited) {
|
||||
variance |= VarianceFlags.Awaited;
|
||||
}
|
||||
variances.push(variance);
|
||||
}
|
||||
cache.variances = variances;
|
||||
@@ -18449,6 +18468,9 @@ namespace ts {
|
||||
if (i < variances.length && (variances[i] & VarianceFlags.VarianceMask) === VarianceFlags.Contravariant) {
|
||||
inferFromContravariantTypes(sourceTypes[i], targetTypes[i]);
|
||||
}
|
||||
else if (variances[i] & VarianceFlags.Awaited) {
|
||||
inferFromTypes(unwrapAwaitedType(sourceTypes[i]), targetTypes[i]);
|
||||
}
|
||||
else {
|
||||
inferFromTypes(sourceTypes[i], targetTypes[i]);
|
||||
}
|
||||
|
||||
+1
-1
@@ -1231,7 +1231,7 @@ namespace ts {
|
||||
enableCPUProfiler,
|
||||
disableCPUProfiler,
|
||||
realpath,
|
||||
debugMode: some(<string[]>process.execArgv, arg => /^--(inspect|debug)(-brk)?(=\d+)?$/i.test(arg)),
|
||||
debugMode: !!process.env.NODE_INSPECTOR_IPC || some(<string[]>process.execArgv, arg => /^--(inspect|debug)(-brk)?(=\d+)?$/i.test(arg)),
|
||||
tryEnableSourceMapsForHost() {
|
||||
try {
|
||||
require("source-map-support").install();
|
||||
|
||||
@@ -641,7 +641,8 @@ namespace ts {
|
||||
|
||||
ReportsUnmeasurable = 1 << 3,
|
||||
ReportsUnreliable = 1 << 4,
|
||||
ReportsMask = ReportsUnmeasurable | ReportsUnreliable
|
||||
ReportsAwaited = 1 << 5,
|
||||
ReportsMask = ReportsUnmeasurable | ReportsUnreliable | ReportsAwaited
|
||||
}
|
||||
|
||||
export interface Node extends TextRange {
|
||||
@@ -4608,7 +4609,8 @@ namespace ts {
|
||||
VarianceMask = Invariant | Covariant | Contravariant | Independent, // Mask containing all measured variances without the unmeasurable flag
|
||||
Unmeasurable = 1 << 3, // Variance result is unusable - relationship relies on structural comparisons which are not reflected in generic relationships
|
||||
Unreliable = 1 << 4, // Variance result is unreliable - checking may produce false negatives, but not false positives
|
||||
AllowsStructuralFallback = Unmeasurable | Unreliable,
|
||||
Awaited = 1 << 5, // type argument is awaited
|
||||
AllowsStructuralFallback = Unmeasurable | Unreliable | Awaited,
|
||||
}
|
||||
|
||||
// Generic class and interface types
|
||||
|
||||
@@ -13,7 +13,12 @@ function f<T>() {
|
||||
}
|
||||
const x = f<number>(); // number
|
||||
const y = f<Promise<number>>(); // number ?
|
||||
const z = f<Promise<number> | number>(); // number ?
|
||||
const z = f<Promise<number> | number>(); // number ?
|
||||
|
||||
// https://github.com/microsoft/TypeScript/issues/37526
|
||||
function f1<T>(a: T): Promise<awaited T> {
|
||||
return new Promise(r => r(a));
|
||||
}
|
||||
|
||||
//// [awaitedInference.js]
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
@@ -62,3 +67,7 @@ function f() {
|
||||
var x = f(); // number
|
||||
var y = f(); // number ?
|
||||
var z = f(); // number ?
|
||||
// https://github.com/microsoft/TypeScript/issues/37526
|
||||
function f1(a) {
|
||||
return new Promise(function (r) { return r(a); });
|
||||
}
|
||||
|
||||
@@ -26,12 +26,12 @@ type UnwrapAwaited<T> = T extends awaited infer Inner ? Inner : T;
|
||||
type Result1 = UnwrapAwaited<awaited Promise<number>>; // number
|
||||
>Result1 : Symbol(Result1, Decl(awaitedInference.ts, 4, 66))
|
||||
>UnwrapAwaited : Symbol(UnwrapAwaited, Decl(awaitedInference.ts, 2, 36))
|
||||
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --))
|
||||
>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, --, --))
|
||||
|
||||
type Result2 = UnwrapAwaited<awaited Promise<number> | number>; // number
|
||||
>Result2 : Symbol(Result2, Decl(awaitedInference.ts, 5, 54))
|
||||
>UnwrapAwaited : Symbol(UnwrapAwaited, Decl(awaitedInference.ts, 2, 36))
|
||||
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --))
|
||||
>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, --, --))
|
||||
|
||||
function f<T>() {
|
||||
>f : Symbol(f, Decl(awaitedInference.ts, 6, 63))
|
||||
@@ -58,10 +58,25 @@ const x = f<number>(); // number
|
||||
const y = f<Promise<number>>(); // number ?
|
||||
>y : Symbol(y, Decl(awaitedInference.ts, 13, 5))
|
||||
>f : Symbol(f, Decl(awaitedInference.ts, 6, 63))
|
||||
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --))
|
||||
>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, --, --))
|
||||
|
||||
const z = f<Promise<number> | number>(); // number ?
|
||||
>z : Symbol(z, Decl(awaitedInference.ts, 14, 5))
|
||||
>f : Symbol(f, Decl(awaitedInference.ts, 6, 63))
|
||||
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --))
|
||||
>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, --, --))
|
||||
|
||||
// https://github.com/microsoft/TypeScript/issues/37526
|
||||
function f1<T>(a: T): Promise<awaited T> {
|
||||
>f1 : Symbol(f1, Decl(awaitedInference.ts, 14, 40))
|
||||
>T : Symbol(T, Decl(awaitedInference.ts, 17, 12))
|
||||
>a : Symbol(a, Decl(awaitedInference.ts, 17, 15))
|
||||
>T : Symbol(T, Decl(awaitedInference.ts, 17, 12))
|
||||
>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, --, --))
|
||||
>T : Symbol(T, Decl(awaitedInference.ts, 17, 12))
|
||||
|
||||
return new Promise(r => r(a));
|
||||
>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, --, --))
|
||||
>r : Symbol(r, Decl(awaitedInference.ts, 18, 23))
|
||||
>r : Symbol(r, Decl(awaitedInference.ts, 18, 23))
|
||||
>a : Symbol(a, Decl(awaitedInference.ts, 17, 15))
|
||||
}
|
||||
|
||||
@@ -53,3 +53,17 @@ const z = f<Promise<number> | number>(); // number ?
|
||||
>f<Promise<number> | number>() : [number | Promise<number>, number]
|
||||
>f : <T>() => [UnwrapAwaited<T>, UnwrapAwaited<awaited T>]
|
||||
|
||||
// https://github.com/microsoft/TypeScript/issues/37526
|
||||
function f1<T>(a: T): Promise<awaited T> {
|
||||
>f1 : <T>(a: T) => Promise<awaited T>
|
||||
>a : T
|
||||
|
||||
return new Promise(r => r(a));
|
||||
>new Promise(r => r(a)) : Promise<T>
|
||||
>Promise : PromiseConstructor
|
||||
>r => r(a) : (r: (value?: T | awaited T | PromiseLike<T>) => void) => void
|
||||
>r : (value?: T | awaited T | PromiseLike<T>) => void
|
||||
>r(a) : void
|
||||
>r : (value?: T | awaited T | PromiseLike<T>) => void
|
||||
>a : T
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// @lib: es2015
|
||||
|
||||
declare function foo<T>(f: () => PromiseLike<T>, x: T): void;
|
||||
declare const nullOrNumber: number | null;
|
||||
foo(async () => nullOrNumber, null);
|
||||
@@ -12,4 +14,9 @@ function f<T>() {
|
||||
}
|
||||
const x = f<number>(); // number
|
||||
const y = f<Promise<number>>(); // number ?
|
||||
const z = f<Promise<number> | number>(); // number ?
|
||||
const z = f<Promise<number> | number>(); // number ?
|
||||
|
||||
// https://github.com/microsoft/TypeScript/issues/37526
|
||||
function f1<T>(a: T): Promise<awaited T> {
|
||||
return new Promise(r => r(a));
|
||||
}
|
||||
Reference in New Issue
Block a user