mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-07 23:08:20 -06:00
Component commits: a81ce061de Stricter criteria for eliminating types in unions during inference f929a25407 Add regression test 6d46850172 Accept new baselines 86d9153374 Accept new API baselines abc61a0949 Add InferencePriority.Circularity per CR feedback ac2f151412 Accept new API baselines c816cf2562 Add additional test af7ccf954a Accept new baselines
This commit is contained in:
parent
3271a1c3cb
commit
03055d2fb6
@ -15486,8 +15486,7 @@ namespace ts {
|
||||
let visited: Map<number>;
|
||||
let bivariant = false;
|
||||
let propagationType: Type;
|
||||
let inferenceMatch = false;
|
||||
let inferenceIncomplete = false;
|
||||
let inferencePriority = InferencePriority.MaxValue;
|
||||
let allowComplexConstraintInference = true;
|
||||
inferFromTypes(originalSource, originalTarget);
|
||||
|
||||
@ -15600,7 +15599,7 @@ namespace ts {
|
||||
clearCachedInferences(inferences);
|
||||
}
|
||||
}
|
||||
inferenceMatch = true;
|
||||
inferencePriority = Math.min(inferencePriority, priority);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
@ -15694,19 +15693,15 @@ namespace ts {
|
||||
const key = source.id + "," + target.id;
|
||||
const status = visited && visited.get(key);
|
||||
if (status !== undefined) {
|
||||
if (status & 1) inferenceMatch = true;
|
||||
if (status & 2) inferenceIncomplete = true;
|
||||
inferencePriority = Math.min(inferencePriority, status);
|
||||
return;
|
||||
}
|
||||
(visited || (visited = createMap<number>())).set(key, 0);
|
||||
const saveInferenceMatch = inferenceMatch;
|
||||
const saveInferenceIncomplete = inferenceIncomplete;
|
||||
inferenceMatch = false;
|
||||
inferenceIncomplete = false;
|
||||
(visited || (visited = createMap<number>())).set(key, InferencePriority.Circularity);
|
||||
const saveInferencePriority = inferencePriority;
|
||||
inferencePriority = InferencePriority.MaxValue;
|
||||
action(source, target);
|
||||
visited.set(key, (inferenceMatch ? 1 : 0) | (inferenceIncomplete ? 2 : 0));
|
||||
inferenceMatch = inferenceMatch || saveInferenceMatch;
|
||||
inferenceIncomplete = inferenceIncomplete || saveInferenceIncomplete;
|
||||
visited.set(key, inferencePriority);
|
||||
inferencePriority = Math.min(inferencePriority, saveInferencePriority);
|
||||
}
|
||||
|
||||
function inferFromMatchingType(source: Type, targets: Type[], matches: (s: Type, t: Type) => boolean) {
|
||||
@ -15778,10 +15773,11 @@ namespace ts {
|
||||
let nakedTypeVariable: Type | undefined;
|
||||
const sources = source.flags & TypeFlags.Union ? (<UnionType>source).types : [source];
|
||||
const matched = new Array<boolean>(sources.length);
|
||||
const saveInferenceIncomplete = inferenceIncomplete;
|
||||
inferenceIncomplete = false;
|
||||
let inferenceCircularity = false;
|
||||
// First infer to types that are not naked type variables. For each source type we
|
||||
// track whether inferences were made from that particular type to some target.
|
||||
// track whether inferences were made from that particular type to some target with
|
||||
// equal priority (i.e. of equal quality) to what we would infer for a naked type
|
||||
// parameter.
|
||||
for (const t of targets) {
|
||||
if (getInferenceInfoForType(t)) {
|
||||
nakedTypeVariable = t;
|
||||
@ -15789,20 +15785,20 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
for (let i = 0; i < sources.length; i++) {
|
||||
const saveInferenceMatch = inferenceMatch;
|
||||
inferenceMatch = false;
|
||||
const saveInferencePriority = inferencePriority;
|
||||
inferencePriority = InferencePriority.MaxValue;
|
||||
inferFromTypes(sources[i], t);
|
||||
if (inferenceMatch) matched[i] = true;
|
||||
inferenceMatch = inferenceMatch || saveInferenceMatch;
|
||||
if (inferencePriority === priority) matched[i] = true;
|
||||
inferenceCircularity = inferenceCircularity || inferencePriority === InferencePriority.Circularity;
|
||||
inferencePriority = Math.min(inferencePriority, saveInferencePriority);
|
||||
}
|
||||
}
|
||||
}
|
||||
const inferenceComplete = !inferenceIncomplete;
|
||||
inferenceIncomplete = inferenceIncomplete || saveInferenceIncomplete;
|
||||
// If the target has a single naked type variable and inference completed (meaning we
|
||||
// explored the types fully), create a union of the source types from which no inferences
|
||||
// have been made so far and infer from that union to the naked type variable.
|
||||
if (typeVariableCount === 1 && inferenceComplete) {
|
||||
// If the target has a single naked type variable and no inference circularities were
|
||||
// encountered above (meaning we explored the types fully), create a union of the source
|
||||
// types from which no inferences have been made so far and infer from that union to the
|
||||
// naked type variable.
|
||||
if (typeVariableCount === 1 && !inferenceCircularity) {
|
||||
const unmatched = flatMap(sources, (s, i) => matched[i] ? undefined : s);
|
||||
if (unmatched.length) {
|
||||
inferFromTypes(getUnionType(unmatched), nakedTypeVariable!);
|
||||
@ -15905,7 +15901,7 @@ namespace ts {
|
||||
const symbol = isNonConstructorObject ? target.symbol : undefined;
|
||||
if (symbol) {
|
||||
if (contains(symbolStack, symbol)) {
|
||||
inferenceIncomplete = true;
|
||||
inferencePriority = InferencePriority.Circularity;
|
||||
return;
|
||||
}
|
||||
(symbolStack || (symbolStack = [])).push(symbol);
|
||||
|
||||
@ -4483,8 +4483,10 @@ namespace ts {
|
||||
LiteralKeyof = 1 << 5, // Inference made from a string literal to a keyof T
|
||||
NoConstraints = 1 << 6, // Don't infer from constraints of instantiable types
|
||||
AlwaysStrict = 1 << 7, // Always use strict rules for contravariant inferences
|
||||
MaxValue = 1 << 8, // Seed for inference priority tracking
|
||||
|
||||
PriorityImpliesCombination = ReturnType | MappedTypeConstraint | LiteralKeyof, // These priorities imply that the resulting type should be a combination of all candidates
|
||||
Circularity = -1, // Inference circularity (value less than all other priorities)
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
|
||||
@ -2441,7 +2441,9 @@ declare namespace ts {
|
||||
LiteralKeyof = 32,
|
||||
NoConstraints = 64,
|
||||
AlwaysStrict = 128,
|
||||
PriorityImpliesCombination = 56
|
||||
MaxValue = 256,
|
||||
PriorityImpliesCombination = 56,
|
||||
Circularity = -1
|
||||
}
|
||||
/** @deprecated Use FileExtensionInfo instead. */
|
||||
export type JsFileExtensionInfo = FileExtensionInfo;
|
||||
|
||||
@ -2441,7 +2441,9 @@ declare namespace ts {
|
||||
LiteralKeyof = 32,
|
||||
NoConstraints = 64,
|
||||
AlwaysStrict = 128,
|
||||
PriorityImpliesCombination = 56
|
||||
MaxValue = 256,
|
||||
PriorityImpliesCombination = 56,
|
||||
Circularity = -1
|
||||
}
|
||||
/** @deprecated Use FileExtensionInfo instead. */
|
||||
export type JsFileExtensionInfo = FileExtensionInfo;
|
||||
|
||||
@ -58,4 +58,30 @@ tests/cases/conformance/types/typeRelationships/typeInference/unionTypeInference
|
||||
|
||||
declare function bar<T>(x: T, y: string | T): T;
|
||||
const y = bar(1, 2);
|
||||
|
||||
// Repro from #32752
|
||||
|
||||
const containsPromises: unique symbol = Symbol();
|
||||
|
||||
type DeepPromised<T> =
|
||||
{ [containsPromises]?: true } &
|
||||
{ [TKey in keyof T]: T[TKey] | DeepPromised<T[TKey]> | Promise<DeepPromised<T[TKey]>> };
|
||||
|
||||
async function fun<T>(deepPromised: DeepPromised<T>) {
|
||||
const deepPromisedWithIndexer: DeepPromised<{ [name: string]: {} | null | undefined }> = deepPromised;
|
||||
for (const value of Object.values(deepPromisedWithIndexer)) {
|
||||
const awaitedValue = await value;
|
||||
if (awaitedValue)
|
||||
await fun(awaitedValue);
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #32752
|
||||
|
||||
type Deep<T> = { [K in keyof T]: T[K] | Deep<T[K]> };
|
||||
|
||||
declare function baz<T>(dp: Deep<T>): T;
|
||||
declare let xx: { a: string | undefined };
|
||||
|
||||
baz(xx);
|
||||
|
||||
@ -50,29 +50,64 @@ foo(x);
|
||||
|
||||
declare function bar<T>(x: T, y: string | T): T;
|
||||
const y = bar(1, 2);
|
||||
|
||||
// Repro from #32752
|
||||
|
||||
const containsPromises: unique symbol = Symbol();
|
||||
|
||||
type DeepPromised<T> =
|
||||
{ [containsPromises]?: true } &
|
||||
{ [TKey in keyof T]: T[TKey] | DeepPromised<T[TKey]> | Promise<DeepPromised<T[TKey]>> };
|
||||
|
||||
async function fun<T>(deepPromised: DeepPromised<T>) {
|
||||
const deepPromisedWithIndexer: DeepPromised<{ [name: string]: {} | null | undefined }> = deepPromised;
|
||||
for (const value of Object.values(deepPromisedWithIndexer)) {
|
||||
const awaitedValue = await value;
|
||||
if (awaitedValue)
|
||||
await fun(awaitedValue);
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #32752
|
||||
|
||||
type Deep<T> = { [K in keyof T]: T[K] | Deep<T[K]> };
|
||||
|
||||
declare function baz<T>(dp: Deep<T>): T;
|
||||
declare let xx: { a: string | undefined };
|
||||
|
||||
baz(xx);
|
||||
|
||||
|
||||
//// [unionTypeInference.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
var a1 = f1(1, 2); // 1 | 2
|
||||
var a2 = f1(1, "hello"); // 1
|
||||
var a3 = f1(1, sn); // number
|
||||
var a4 = f1(undefined, "abc"); // undefined
|
||||
var a5 = f1("foo", "bar"); // "foo"
|
||||
var a6 = f1(true, false); // boolean
|
||||
var a7 = f1("hello", 1); // Error
|
||||
const a1 = f1(1, 2); // 1 | 2
|
||||
const a2 = f1(1, "hello"); // 1
|
||||
const a3 = f1(1, sn); // number
|
||||
const a4 = f1(undefined, "abc"); // undefined
|
||||
const a5 = f1("foo", "bar"); // "foo"
|
||||
const a6 = f1(true, false); // boolean
|
||||
const a7 = f1("hello", 1); // Error
|
||||
var b1 = f2(["string", true]); // boolean
|
||||
var c1 = f3(5); // 5
|
||||
var c2 = f3(sn); // number
|
||||
var c3 = f3(true); // true
|
||||
var c4 = f3(b); // true
|
||||
var c5 = f3("abc"); // never
|
||||
var d1 = f4("abc");
|
||||
var d2 = f4(s);
|
||||
var d3 = f4(42); // Error
|
||||
const c1 = f3(5); // 5
|
||||
const c2 = f3(sn); // number
|
||||
const c3 = f3(true); // true
|
||||
const c4 = f3(b); // true
|
||||
const c5 = f3("abc"); // never
|
||||
const d1 = f4("abc");
|
||||
const d2 = f4(s);
|
||||
const d3 = f4(42); // Error
|
||||
function qux(p1, p2) {
|
||||
p1 = p2;
|
||||
}
|
||||
foo(x);
|
||||
var y = bar(1, 2);
|
||||
const y = bar(1, 2);
|
||||
// Repro from #32752
|
||||
const containsPromises = Symbol();
|
||||
async function fun(deepPromised) {
|
||||
const deepPromisedWithIndexer = deepPromised;
|
||||
for (const value of Object.values(deepPromisedWithIndexer)) {
|
||||
const awaitedValue = await value;
|
||||
if (awaitedValue)
|
||||
await fun(awaitedValue);
|
||||
}
|
||||
}
|
||||
baz(xx);
|
||||
|
||||
@ -163,12 +163,12 @@ declare function foo<T>(x: T | Promise<T>): void;
|
||||
>T : Symbol(T, Decl(unionTypeInference.ts, 45, 21))
|
||||
>x : Symbol(x, Decl(unionTypeInference.ts, 45, 24))
|
||||
>T : Symbol(T, Decl(unionTypeInference.ts, 45, 21))
|
||||
>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, --, --), Decl(lib.es2018.promise.d.ts, --, --))
|
||||
>T : Symbol(T, Decl(unionTypeInference.ts, 45, 21))
|
||||
|
||||
declare let x: false | Promise<true>;
|
||||
>x : Symbol(x, Decl(unionTypeInference.ts, 46, 11))
|
||||
>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, --, --), Decl(lib.es2018.promise.d.ts, --, --))
|
||||
|
||||
foo(x);
|
||||
>foo : Symbol(foo, Decl(unionTypeInference.ts, 41, 1))
|
||||
@ -187,3 +187,92 @@ const y = bar(1, 2);
|
||||
>y : Symbol(y, Decl(unionTypeInference.ts, 50, 5))
|
||||
>bar : Symbol(bar, Decl(unionTypeInference.ts, 47, 7))
|
||||
|
||||
// Repro from #32752
|
||||
|
||||
const containsPromises: unique symbol = Symbol();
|
||||
>containsPromises : Symbol(containsPromises, Decl(unionTypeInference.ts, 54, 5))
|
||||
>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --))
|
||||
|
||||
type DeepPromised<T> =
|
||||
>DeepPromised : Symbol(DeepPromised, Decl(unionTypeInference.ts, 54, 49))
|
||||
>T : Symbol(T, Decl(unionTypeInference.ts, 56, 18))
|
||||
|
||||
{ [containsPromises]?: true } &
|
||||
>[containsPromises] : Symbol([containsPromises], Decl(unionTypeInference.ts, 57, 5))
|
||||
>containsPromises : Symbol(containsPromises, Decl(unionTypeInference.ts, 54, 5))
|
||||
|
||||
{ [TKey in keyof T]: T[TKey] | DeepPromised<T[TKey]> | Promise<DeepPromised<T[TKey]>> };
|
||||
>TKey : Symbol(TKey, Decl(unionTypeInference.ts, 58, 7))
|
||||
>T : Symbol(T, Decl(unionTypeInference.ts, 56, 18))
|
||||
>T : Symbol(T, Decl(unionTypeInference.ts, 56, 18))
|
||||
>TKey : Symbol(TKey, Decl(unionTypeInference.ts, 58, 7))
|
||||
>DeepPromised : Symbol(DeepPromised, Decl(unionTypeInference.ts, 54, 49))
|
||||
>T : Symbol(T, Decl(unionTypeInference.ts, 56, 18))
|
||||
>TKey : Symbol(TKey, Decl(unionTypeInference.ts, 58, 7))
|
||||
>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, --, --))
|
||||
>DeepPromised : Symbol(DeepPromised, Decl(unionTypeInference.ts, 54, 49))
|
||||
>T : Symbol(T, Decl(unionTypeInference.ts, 56, 18))
|
||||
>TKey : Symbol(TKey, Decl(unionTypeInference.ts, 58, 7))
|
||||
|
||||
async function fun<T>(deepPromised: DeepPromised<T>) {
|
||||
>fun : Symbol(fun, Decl(unionTypeInference.ts, 58, 92))
|
||||
>T : Symbol(T, Decl(unionTypeInference.ts, 60, 19))
|
||||
>deepPromised : Symbol(deepPromised, Decl(unionTypeInference.ts, 60, 22))
|
||||
>DeepPromised : Symbol(DeepPromised, Decl(unionTypeInference.ts, 54, 49))
|
||||
>T : Symbol(T, Decl(unionTypeInference.ts, 60, 19))
|
||||
|
||||
const deepPromisedWithIndexer: DeepPromised<{ [name: string]: {} | null | undefined }> = deepPromised;
|
||||
>deepPromisedWithIndexer : Symbol(deepPromisedWithIndexer, Decl(unionTypeInference.ts, 61, 9))
|
||||
>DeepPromised : Symbol(DeepPromised, Decl(unionTypeInference.ts, 54, 49))
|
||||
>name : Symbol(name, Decl(unionTypeInference.ts, 61, 51))
|
||||
>deepPromised : Symbol(deepPromised, Decl(unionTypeInference.ts, 60, 22))
|
||||
|
||||
for (const value of Object.values(deepPromisedWithIndexer)) {
|
||||
>value : Symbol(value, Decl(unionTypeInference.ts, 62, 14))
|
||||
>Object.values : Symbol(ObjectConstructor.values, Decl(lib.es2017.object.d.ts, --, --), Decl(lib.es2017.object.d.ts, --, --))
|
||||
>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
>values : Symbol(ObjectConstructor.values, Decl(lib.es2017.object.d.ts, --, --), Decl(lib.es2017.object.d.ts, --, --))
|
||||
>deepPromisedWithIndexer : Symbol(deepPromisedWithIndexer, Decl(unionTypeInference.ts, 61, 9))
|
||||
|
||||
const awaitedValue = await value;
|
||||
>awaitedValue : Symbol(awaitedValue, Decl(unionTypeInference.ts, 63, 13))
|
||||
>value : Symbol(value, Decl(unionTypeInference.ts, 62, 14))
|
||||
|
||||
if (awaitedValue)
|
||||
>awaitedValue : Symbol(awaitedValue, Decl(unionTypeInference.ts, 63, 13))
|
||||
|
||||
await fun(awaitedValue);
|
||||
>fun : Symbol(fun, Decl(unionTypeInference.ts, 58, 92))
|
||||
>awaitedValue : Symbol(awaitedValue, Decl(unionTypeInference.ts, 63, 13))
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #32752
|
||||
|
||||
type Deep<T> = { [K in keyof T]: T[K] | Deep<T[K]> };
|
||||
>Deep : Symbol(Deep, Decl(unionTypeInference.ts, 67, 1))
|
||||
>T : Symbol(T, Decl(unionTypeInference.ts, 71, 10))
|
||||
>K : Symbol(K, Decl(unionTypeInference.ts, 71, 18))
|
||||
>T : Symbol(T, Decl(unionTypeInference.ts, 71, 10))
|
||||
>T : Symbol(T, Decl(unionTypeInference.ts, 71, 10))
|
||||
>K : Symbol(K, Decl(unionTypeInference.ts, 71, 18))
|
||||
>Deep : Symbol(Deep, Decl(unionTypeInference.ts, 67, 1))
|
||||
>T : Symbol(T, Decl(unionTypeInference.ts, 71, 10))
|
||||
>K : Symbol(K, Decl(unionTypeInference.ts, 71, 18))
|
||||
|
||||
declare function baz<T>(dp: Deep<T>): T;
|
||||
>baz : Symbol(baz, Decl(unionTypeInference.ts, 71, 53))
|
||||
>T : Symbol(T, Decl(unionTypeInference.ts, 73, 21))
|
||||
>dp : Symbol(dp, Decl(unionTypeInference.ts, 73, 24))
|
||||
>Deep : Symbol(Deep, Decl(unionTypeInference.ts, 67, 1))
|
||||
>T : Symbol(T, Decl(unionTypeInference.ts, 73, 21))
|
||||
>T : Symbol(T, Decl(unionTypeInference.ts, 73, 21))
|
||||
|
||||
declare let xx: { a: string | undefined };
|
||||
>xx : Symbol(xx, Decl(unionTypeInference.ts, 74, 11))
|
||||
>a : Symbol(a, Decl(unionTypeInference.ts, 74, 17))
|
||||
|
||||
baz(xx);
|
||||
>baz : Symbol(baz, Decl(unionTypeInference.ts, 71, 53))
|
||||
>xx : Symbol(xx, Decl(unionTypeInference.ts, 74, 11))
|
||||
|
||||
|
||||
@ -185,3 +185,72 @@ const y = bar(1, 2);
|
||||
>1 : 1
|
||||
>2 : 2
|
||||
|
||||
// Repro from #32752
|
||||
|
||||
const containsPromises: unique symbol = Symbol();
|
||||
>containsPromises : unique symbol
|
||||
>Symbol() : unique symbol
|
||||
>Symbol : SymbolConstructor
|
||||
|
||||
type DeepPromised<T> =
|
||||
>DeepPromised : DeepPromised<T>
|
||||
|
||||
{ [containsPromises]?: true } &
|
||||
>[containsPromises] : true | undefined
|
||||
>containsPromises : unique symbol
|
||||
>true : true
|
||||
|
||||
{ [TKey in keyof T]: T[TKey] | DeepPromised<T[TKey]> | Promise<DeepPromised<T[TKey]>> };
|
||||
|
||||
async function fun<T>(deepPromised: DeepPromised<T>) {
|
||||
>fun : <T>(deepPromised: DeepPromised<T>) => Promise<void>
|
||||
>deepPromised : DeepPromised<T>
|
||||
|
||||
const deepPromisedWithIndexer: DeepPromised<{ [name: string]: {} | null | undefined }> = deepPromised;
|
||||
>deepPromisedWithIndexer : DeepPromised<{ [name: string]: {} | null | undefined; }>
|
||||
>name : string
|
||||
>null : null
|
||||
>deepPromised : DeepPromised<T>
|
||||
|
||||
for (const value of Object.values(deepPromisedWithIndexer)) {
|
||||
>value : {} | ({ [containsPromises]?: true | undefined; } & {}) | Promise<{ [containsPromises]?: true | undefined; } & {}> | null | undefined
|
||||
>Object.values(deepPromisedWithIndexer) : ({} | ({ [containsPromises]?: true | undefined; } & {}) | Promise<{ [containsPromises]?: true | undefined; } & {}> | null | undefined)[]
|
||||
>Object.values : { <T>(o: { [s: string]: T; } | ArrayLike<T>): T[]; (o: {}): any[]; }
|
||||
>Object : ObjectConstructor
|
||||
>values : { <T>(o: { [s: string]: T; } | ArrayLike<T>): T[]; (o: {}): any[]; }
|
||||
>deepPromisedWithIndexer : DeepPromised<{ [name: string]: {} | null | undefined; }>
|
||||
|
||||
const awaitedValue = await value;
|
||||
>awaitedValue : {} | ({ [containsPromises]?: true | undefined; } & {}) | null | undefined
|
||||
>await value : {} | ({ [containsPromises]?: true | undefined; } & {}) | null | undefined
|
||||
>value : {} | ({ [containsPromises]?: true | undefined; } & {}) | Promise<{ [containsPromises]?: true | undefined; } & {}> | null | undefined
|
||||
|
||||
if (awaitedValue)
|
||||
>awaitedValue : {} | ({ [containsPromises]?: true | undefined; } & {}) | null | undefined
|
||||
|
||||
await fun(awaitedValue);
|
||||
>await fun(awaitedValue) : void
|
||||
>fun(awaitedValue) : Promise<void>
|
||||
>fun : <T>(deepPromised: DeepPromised<T>) => Promise<void>
|
||||
>awaitedValue : {} | ({ [containsPromises]?: true | undefined; } & {})
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #32752
|
||||
|
||||
type Deep<T> = { [K in keyof T]: T[K] | Deep<T[K]> };
|
||||
>Deep : Deep<T>
|
||||
|
||||
declare function baz<T>(dp: Deep<T>): T;
|
||||
>baz : <T>(dp: Deep<T>) => T
|
||||
>dp : Deep<T>
|
||||
|
||||
declare let xx: { a: string | undefined };
|
||||
>xx : { a: string | undefined; }
|
||||
>a : string | undefined
|
||||
|
||||
baz(xx);
|
||||
>baz(xx) : { a: string | undefined; }
|
||||
>baz : <T>(dp: Deep<T>) => T
|
||||
>xx : { a: string | undefined; }
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
// @strict: true
|
||||
// @target: esnext
|
||||
|
||||
declare const b: boolean;
|
||||
declare const s: string;
|
||||
@ -51,3 +52,29 @@ foo(x);
|
||||
|
||||
declare function bar<T>(x: T, y: string | T): T;
|
||||
const y = bar(1, 2);
|
||||
|
||||
// Repro from #32752
|
||||
|
||||
const containsPromises: unique symbol = Symbol();
|
||||
|
||||
type DeepPromised<T> =
|
||||
{ [containsPromises]?: true } &
|
||||
{ [TKey in keyof T]: T[TKey] | DeepPromised<T[TKey]> | Promise<DeepPromised<T[TKey]>> };
|
||||
|
||||
async function fun<T>(deepPromised: DeepPromised<T>) {
|
||||
const deepPromisedWithIndexer: DeepPromised<{ [name: string]: {} | null | undefined }> = deepPromised;
|
||||
for (const value of Object.values(deepPromisedWithIndexer)) {
|
||||
const awaitedValue = await value;
|
||||
if (awaitedValue)
|
||||
await fun(awaitedValue);
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #32752
|
||||
|
||||
type Deep<T> = { [K in keyof T]: T[K] | Deep<T[K]> };
|
||||
|
||||
declare function baz<T>(dp: Deep<T>): T;
|
||||
declare let xx: { a: string | undefined };
|
||||
|
||||
baz(xx);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user