mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-10 06:41:59 -06:00
Add inference based for 'Promise' based on call to 'resolve'
This commit is contained in:
parent
6aec7f4676
commit
56a9871ff3
@ -19458,7 +19458,7 @@ namespace ts {
|
||||
source = getUnionType(sources);
|
||||
}
|
||||
else if (target.flags & TypeFlags.Intersection && some((<IntersectionType>target).types,
|
||||
t => !!getInferenceInfoForType(t) || (isGenericMappedType(t) && !!getInferenceInfoForType(getHomomorphicTypeVariable(t) || neverType)))) {
|
||||
t => !!getInferenceInfoForType(inferences, t) || (isGenericMappedType(t) && !!getInferenceInfoForType(inferences, getHomomorphicTypeVariable(t) || neverType)))) {
|
||||
// We reduce intersection types only when they contain naked type parameters. For example, when
|
||||
// inferring from 'string[] & { extra: any }' to 'string[] & T' we want to remove string[] and
|
||||
// infer { extra: any } for T. But when inferring to 'string[] & Iterable<T>' we want to keep the
|
||||
@ -19490,7 +19490,7 @@ namespace ts {
|
||||
(priority & InferencePriority.ReturnType && (source === autoType || source === autoArrayType)) || isFromInferenceBlockedSource(source)) {
|
||||
return;
|
||||
}
|
||||
const inference = getInferenceInfoForType(target);
|
||||
const inference = getInferenceInfoForType(inferences, target);
|
||||
if (inference) {
|
||||
if (!inference.isFixed) {
|
||||
if (inference.priority === undefined || priority < inference.priority) {
|
||||
@ -19687,21 +19687,10 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function getInferenceInfoForType(type: Type) {
|
||||
if (type.flags & TypeFlags.TypeVariable) {
|
||||
for (const inference of inferences) {
|
||||
if (type === inference.typeParameter) {
|
||||
return inference;
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getSingleTypeVariableFromIntersectionTypes(types: Type[]) {
|
||||
let typeVariable: Type | undefined;
|
||||
for (const type of types) {
|
||||
const t = type.flags & TypeFlags.Intersection && find((<IntersectionType>type).types, t => !!getInferenceInfoForType(t));
|
||||
const t = type.flags & TypeFlags.Intersection && find((<IntersectionType>type).types, t => !!getInferenceInfoForType(inferences, t));
|
||||
if (!t || typeVariable && t !== typeVariable) {
|
||||
return undefined;
|
||||
}
|
||||
@ -19722,7 +19711,7 @@ namespace ts {
|
||||
// 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)) {
|
||||
if (getInferenceInfoForType(inferences, t)) {
|
||||
nakedTypeVariable = t;
|
||||
typeVariableCount++;
|
||||
}
|
||||
@ -19764,7 +19753,7 @@ namespace ts {
|
||||
// make from nested naked type variables and given slightly higher priority by virtue
|
||||
// of being first in the candidates array.
|
||||
for (const t of targets) {
|
||||
if (getInferenceInfoForType(t)) {
|
||||
if (getInferenceInfoForType(inferences, t)) {
|
||||
typeVariableCount++;
|
||||
}
|
||||
else {
|
||||
@ -19778,7 +19767,7 @@ namespace ts {
|
||||
// we only infer to single naked type variables.
|
||||
if (targetFlags & TypeFlags.Intersection ? typeVariableCount === 1 : typeVariableCount > 0) {
|
||||
for (const t of targets) {
|
||||
if (getInferenceInfoForType(t)) {
|
||||
if (getInferenceInfoForType(inferences, t)) {
|
||||
inferWithPriority(source, t, InferencePriority.NakedTypeVariable);
|
||||
}
|
||||
}
|
||||
@ -19798,7 +19787,7 @@ namespace ts {
|
||||
// where T is a type variable. Use inferTypeForHomomorphicMappedType to infer a suitable source
|
||||
// type and then make a secondary inference from that type to T. We make a secondary inference
|
||||
// such that direct inferences to T get priority over inferences to Partial<T>, for example.
|
||||
const inference = getInferenceInfoForType((<IndexType>constraintType).type);
|
||||
const inference = getInferenceInfoForType(inferences, (<IndexType>constraintType).type);
|
||||
if (inference && !inference.isFixed && !isFromInferenceBlockedSource(source)) {
|
||||
const inferredType = inferTypeForHomomorphicMappedType(source, target, <IndexType>constraintType);
|
||||
if (inferredType) {
|
||||
@ -19909,7 +19898,7 @@ namespace ts {
|
||||
const middleLength = targetArity - startLength - endLength;
|
||||
if (middleLength === 2 && elementFlags[startLength] & elementFlags[startLength + 1] & ElementFlags.Variadic && isTupleType(source)) {
|
||||
// Middle of target is [...T, ...U] and source is tuple type
|
||||
const targetInfo = getInferenceInfoForType(elementTypes[startLength]);
|
||||
const targetInfo = getInferenceInfoForType(inferences, elementTypes[startLength]);
|
||||
if (targetInfo && targetInfo.impliedArity !== undefined) {
|
||||
// Infer slices from source based on implied arity of T.
|
||||
inferFromTypes(sliceTupleType(source, startLength, sourceEndLength + sourceArity - targetInfo.impliedArity), elementTypes[startLength]);
|
||||
@ -20004,6 +19993,22 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function getInferenceInfoForType(inferences: InferenceInfo[], type: Type) {
|
||||
if (type.flags & TypeFlags.TypeVariable) {
|
||||
for (const inference of inferences) {
|
||||
if (type === inference.typeParameter) {
|
||||
return inference;
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function hasHigherPriorityInference(inferences: InferenceInfo[], type: Type, priority: InferencePriority) {
|
||||
const inference = getInferenceInfoForType(inferences, type);
|
||||
return !!inference && (inference.isFixed || inference.priority !== undefined && inference.priority < priority);
|
||||
}
|
||||
|
||||
function isTypeOrBaseIdenticalTo(s: Type, t: Type) {
|
||||
return isTypeIdenticalTo(s, t) || !!(t.flags & TypeFlags.String && s.flags & TypeFlags.StringLiteral || t.flags & TypeFlags.Number && s.flags & TypeFlags.NumberLiteral);
|
||||
}
|
||||
@ -20661,7 +20666,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function isTypeSubsetOf(source: Type, target: Type) {
|
||||
return source === target || target.flags & TypeFlags.Union && isTypeSubsetOfUnion(source, <UnionType>target);
|
||||
return source === target || !!(target.flags & TypeFlags.Union) && isTypeSubsetOfUnion(source, <UnionType>target);
|
||||
}
|
||||
|
||||
function isTypeSubsetOfUnion(source: Type, target: UnionType) {
|
||||
@ -26020,6 +26025,75 @@ namespace ts {
|
||||
inferTypes(context.inferences, spreadType, restType);
|
||||
}
|
||||
|
||||
// Attempt to solve for `T` in `new Promise<T>(resolve => resolve(t))` (also known as the "revealing constructor" pattern).
|
||||
// To avoid too much complexity, we use a very restrictive heuristic:
|
||||
// - Restrict to NewExpression to reduce overhead.
|
||||
// - `signature` has a single parameter (`callbackType`)
|
||||
// - `callbackType` has a single call signature (`callbackSignature`) (i.e., `executor: (resolve: (value: T | PromiseLike<T>) => void) => void`)
|
||||
// - `callbackSignature` has at least one parameter (`innerCallbackType`)
|
||||
// - `innerCallbackType` has a single call signature (`innerCallbackSignature`) (i.e., `resolve: (value: T | PromiseLike<T>) => void`)
|
||||
// - `innerCallbackSignature` has a single parameter (`innerCallbackValueType`)
|
||||
// - `innerCallbackValueType` contains type variable for which we are gathering inferences (i.e. `value: T | PromiseLike<T>`)
|
||||
// - The function (`callbackFunc`) passed as the argument to the parameter `callbackType` must be inline (i.e., an arrow function or function expression)
|
||||
// - `callbackFunc` must have one parameter (`innerCallbackParam`) that is untyped (and thus would be contextually typed by `innerCallbackType`)
|
||||
// If the above conditions are met then:
|
||||
// - Determine the name in function `callbackFunc` given to the parameter `innerCallbackParam`
|
||||
// - Find all references to that name in the body of the function `callbackFunc`
|
||||
// - If `innerCallbackParam` is called directly, collect inferences for the type of the argument passed to the parameter (`innerCallbackValueType`) each call to `innerCallbackParam`
|
||||
// - If `innerCallbackParam` is passed as the argument to another function, we can attempt to use the contextual type of that parameter for inference.
|
||||
if (isNewExpression(node) && argCount === 1) {
|
||||
const callbackType = getTypeAtPosition(signature, 0); // executor: ...
|
||||
const callbackSignature = getSingleCallSignature(callbackType); // (resolve: (...) => ...) => ...
|
||||
const callbackFunc = skipParentheses(args[0]);
|
||||
if (callbackSignature && isFunctionExpressionOrArrowFunction(callbackFunc)) {
|
||||
const sourceFile = getSourceFileOfNode(callbackFunc);
|
||||
for (let callbackParamIndex = 0; callbackParamIndex < callbackFunc.parameters.length; callbackParamIndex++) {
|
||||
const innerCallbackType = tryGetTypeAtPosition(callbackSignature, callbackParamIndex); // resolve: ...
|
||||
const innerCallbackSignature = innerCallbackType && getSingleCallSignature(innerCallbackType); // (value: T | PromiseLike<T>) => ...
|
||||
const innerCallbackParam = callbackFunc.parameters[callbackParamIndex];
|
||||
if (innerCallbackSignature && getParameterCount(innerCallbackSignature) === 1 && isIdentifier(innerCallbackParam.name) && !getEffectiveTypeAnnotationNode(innerCallbackParam)) {
|
||||
const innerCallbackValueType = getTypeAtPosition(innerCallbackSignature, 0); // value: ...
|
||||
// Don't do the work if we already have a higher-priority inference.
|
||||
if (some(signature.typeParameters, typeParam => isTypeSubsetOf(typeParam, innerCallbackValueType) && !hasHigherPriorityInference(context.inferences, typeParam, InferencePriority.RevealingConstructor))) {
|
||||
const innerCallbackSymbol = getSymbolOfNode(innerCallbackParam);
|
||||
const positions = getPossibleSymbolReferencePositions(sourceFile, idText(innerCallbackParam.name), callbackFunc);
|
||||
if (positions.length) {
|
||||
const candidateReferences = findNodesAtPositions(callbackFunc, positions, sourceFile);
|
||||
if (candidateReferences.length) {
|
||||
// The callback will not have a type associated with it, so we temporarily assign it `anyFunctionType` so that
|
||||
// we do not trigger implicit `any` errors and so that we do not create inferences from it.
|
||||
const links = getSymbolLinks(innerCallbackSymbol);
|
||||
const savedType = links.type;
|
||||
links.type = anyFunctionType;
|
||||
// collect types for inferences to ppB
|
||||
for (const candidateReference of candidateReferences) {
|
||||
if (!isIdentifier(candidateReference) || candidateReference === innerCallbackParam.name) continue;
|
||||
const candidateReferenceSymbol = resolveName(candidateReference, candidateReference.escapedText, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false);
|
||||
if (candidateReferenceSymbol !== innerCallbackSymbol) continue;
|
||||
if (isCallExpression(candidateReference.parent) && candidateReference === candidateReference.parent.expression) {
|
||||
const argType =
|
||||
candidateReference.parent.arguments.length >= 1 ? checkExpression(candidateReference.parent.arguments[0]) :
|
||||
voidType;
|
||||
inferTypes(context.inferences, argType, innerCallbackValueType, InferencePriority.RevealingConstructor);
|
||||
}
|
||||
else if (isCallOrNewExpression(candidateReference.parent) && contains(candidateReference.parent.arguments, candidateReference)) {
|
||||
const callbackType = getContextualType(candidateReference);
|
||||
const callbackSignature = callbackType && getSingleCallSignature(callbackType);
|
||||
const callbackParamType = callbackSignature && tryGetTypeAtPosition(callbackSignature, 0);
|
||||
if (callbackParamType) {
|
||||
inferTypes(context.inferences, callbackParamType, innerCallbackValueType, InferencePriority.RevealingConstructor);
|
||||
}
|
||||
}
|
||||
}
|
||||
links.type = savedType;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return getInferredTypes(context);
|
||||
}
|
||||
|
||||
|
||||
@ -5437,10 +5437,11 @@ namespace ts {
|
||||
ReturnType = 1 << 6, // Inference made from return type of generic function
|
||||
LiteralKeyof = 1 << 7, // Inference made from a string literal to a keyof T
|
||||
NoConstraints = 1 << 8, // Don't infer from constraints of instantiable types
|
||||
AlwaysStrict = 1 << 9, // Always use strict rules for contravariant inferences
|
||||
MaxValue = 1 << 10, // Seed for inference priority tracking
|
||||
RevealingConstructor = 1 << 9, // Inference made to a callback in a "revealing constructor" (i.e., `new Promise(resolve => resolve(1))`)
|
||||
AlwaysStrict = 1 << 10, // Always use strict rules for contravariant inferences
|
||||
MaxValue = 1 << 11, // Seed for inference priority tracking
|
||||
|
||||
PriorityImpliesCombination = ReturnType | MappedTypeConstraint | LiteralKeyof, // These priorities imply that the resulting type should be a combination of all candidates
|
||||
PriorityImpliesCombination = ReturnType | MappedTypeConstraint | LiteralKeyof | RevealingConstructor, // These priorities imply that the resulting type should be a combination of all candidates
|
||||
Circularity = -1, // Inference circularity (value less than all other priorities)
|
||||
}
|
||||
|
||||
|
||||
@ -6903,4 +6903,77 @@ namespace ts {
|
||||
return bindParentToChildIgnoringJSDoc(child, parent) || bindJSDoc(child);
|
||||
}
|
||||
}
|
||||
|
||||
export function getPossibleSymbolReferencePositions(sourceFile: SourceFile, symbolName: string, container: Node = sourceFile) {
|
||||
const positions: number[] = [];
|
||||
|
||||
/// TODO: Cache symbol existence for files to save text search
|
||||
// Also, need to make this work for unicode escapes.
|
||||
|
||||
// Be resilient in the face of a symbol with no name or zero length name
|
||||
if (!symbolName || !symbolName.length) {
|
||||
return positions as readonly number[] as SortedReadonlyArray<number>;
|
||||
}
|
||||
|
||||
const text = sourceFile.text;
|
||||
const sourceLength = text.length;
|
||||
const symbolNameLength = symbolName.length;
|
||||
|
||||
let position = text.indexOf(symbolName, container.pos);
|
||||
while (position >= 0) {
|
||||
// If we are past the end, stop looking
|
||||
if (position > container.end) break;
|
||||
|
||||
// We found a match. Make sure it's not part of a larger word (i.e. the char
|
||||
// before and after it have to be a non-identifier char).
|
||||
const endPosition = position + symbolNameLength;
|
||||
|
||||
if ((position === 0 || !isIdentifierPart(text.charCodeAt(position - 1), ScriptTarget.Latest)) &&
|
||||
(endPosition === sourceLength || !isIdentifierPart(text.charCodeAt(endPosition), ScriptTarget.Latest))) {
|
||||
// Found a real match. Keep searching.
|
||||
positions.push(position);
|
||||
}
|
||||
position = text.indexOf(symbolName, position + symbolNameLength + 1);
|
||||
}
|
||||
|
||||
return positions as readonly number[] as SortedReadonlyArray<number>;
|
||||
}
|
||||
|
||||
export function findNodesAtPositions(container: Node, positions: SortedReadonlyArray<number>, sourceFile = getSourceFileOfNode(container)) {
|
||||
let i = 0;
|
||||
const results: Node[] = [];
|
||||
visit(container);
|
||||
return results;
|
||||
function visit(node: Node) {
|
||||
const startPos = skipTrivia(sourceFile.text, node.pos);
|
||||
while (i < positions.length) {
|
||||
const pos = positions[i];
|
||||
const startOffset = i;
|
||||
if (pos >= node.pos && pos < node.end) {
|
||||
if (pos < startPos) {
|
||||
// The position exists in the node's trivia, so we should skip it and
|
||||
// move on to the next position
|
||||
i++;
|
||||
}
|
||||
else {
|
||||
const length = results.length;
|
||||
forEachChild(node, visit);
|
||||
if (length === results.length) {
|
||||
// no children were added, so add this node
|
||||
results.push(node);
|
||||
// advance to the next position
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// If we've advanced past the end of our parent we should break out of
|
||||
// the containing `forEachChild`. Otherwise, the position is not contained
|
||||
// within this node so we should skip to the next node
|
||||
return !!node.parent && pos > node.parent.end;
|
||||
}
|
||||
Debug.assert(i !== startOffset, "Position did not advance");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1261,41 +1261,6 @@ namespace ts.FindAllReferences {
|
||||
return getPossibleSymbolReferencePositions(sourceFile, symbolName, container).map(pos => getTouchingPropertyName(sourceFile, pos));
|
||||
}
|
||||
|
||||
function getPossibleSymbolReferencePositions(sourceFile: SourceFile, symbolName: string, container: Node = sourceFile): readonly number[] {
|
||||
const positions: number[] = [];
|
||||
|
||||
/// TODO: Cache symbol existence for files to save text search
|
||||
// Also, need to make this work for unicode escapes.
|
||||
|
||||
// Be resilient in the face of a symbol with no name or zero length name
|
||||
if (!symbolName || !symbolName.length) {
|
||||
return positions;
|
||||
}
|
||||
|
||||
const text = sourceFile.text;
|
||||
const sourceLength = text.length;
|
||||
const symbolNameLength = symbolName.length;
|
||||
|
||||
let position = text.indexOf(symbolName, container.pos);
|
||||
while (position >= 0) {
|
||||
// If we are past the end, stop looking
|
||||
if (position > container.end) break;
|
||||
|
||||
// We found a match. Make sure it's not part of a larger word (i.e. the char
|
||||
// before and after it have to be a non-identifier char).
|
||||
const endPosition = position + symbolNameLength;
|
||||
|
||||
if ((position === 0 || !isIdentifierPart(text.charCodeAt(position - 1), ScriptTarget.Latest)) &&
|
||||
(endPosition === sourceLength || !isIdentifierPart(text.charCodeAt(endPosition), ScriptTarget.Latest))) {
|
||||
// Found a real match. Keep searching.
|
||||
positions.push(position);
|
||||
}
|
||||
position = text.indexOf(symbolName, position + symbolNameLength + 1);
|
||||
}
|
||||
|
||||
return positions;
|
||||
}
|
||||
|
||||
function getLabelReferencesInNode(container: Node, targetLabel: Identifier): SymbolAndEntries[] {
|
||||
const sourceFile = container.getSourceFile();
|
||||
const labelName = targetLabel.text;
|
||||
|
||||
@ -2651,9 +2651,10 @@ declare namespace ts {
|
||||
ReturnType = 64,
|
||||
LiteralKeyof = 128,
|
||||
NoConstraints = 256,
|
||||
AlwaysStrict = 512,
|
||||
MaxValue = 1024,
|
||||
PriorityImpliesCombination = 208,
|
||||
RevealingConstructor = 512,
|
||||
AlwaysStrict = 1024,
|
||||
MaxValue = 2048,
|
||||
PriorityImpliesCombination = 720,
|
||||
Circularity = -1
|
||||
}
|
||||
/** @deprecated Use FileExtensionInfo instead. */
|
||||
|
||||
@ -2651,9 +2651,10 @@ declare namespace ts {
|
||||
ReturnType = 64,
|
||||
LiteralKeyof = 128,
|
||||
NoConstraints = 256,
|
||||
AlwaysStrict = 512,
|
||||
MaxValue = 1024,
|
||||
PriorityImpliesCombination = 208,
|
||||
RevealingConstructor = 512,
|
||||
AlwaysStrict = 1024,
|
||||
MaxValue = 2048,
|
||||
PriorityImpliesCombination = 720,
|
||||
Circularity = -1
|
||||
}
|
||||
/** @deprecated Use FileExtensionInfo instead. */
|
||||
|
||||
@ -1,21 +1,21 @@
|
||||
=== tests/cases/conformance/es6/modules/a.ts ===
|
||||
const x = new Promise( ( resolve, reject ) => { resolve( {} ); } );
|
||||
>x : Promise<unknown>
|
||||
>new Promise( ( resolve, reject ) => { resolve( {} ); } ) : Promise<unknown>
|
||||
>x : Promise<{}>
|
||||
>new Promise( ( resolve, reject ) => { resolve( {} ); } ) : Promise<{}>
|
||||
>Promise : PromiseConstructor
|
||||
>( resolve, reject ) => { resolve( {} ); } : (resolve: (value: unknown) => void, reject: (reason?: any) => void) => void
|
||||
>resolve : (value: unknown) => void
|
||||
>( resolve, reject ) => { resolve( {} ); } : (resolve: (value: {} | PromiseLike<{}>) => void, reject: (reason?: any) => void) => void
|
||||
>resolve : (value: {} | PromiseLike<{}>) => void
|
||||
>reject : (reason?: any) => void
|
||||
>resolve( {} ) : void
|
||||
>resolve : (value: unknown) => void
|
||||
>resolve : (value: {} | PromiseLike<{}>) => void
|
||||
>{} : {}
|
||||
|
||||
export default x;
|
||||
>x : Promise<unknown>
|
||||
>x : Promise<{}>
|
||||
|
||||
=== tests/cases/conformance/es6/modules/b.ts ===
|
||||
import x from './a';
|
||||
>x : Promise<unknown>
|
||||
>x : Promise<{}>
|
||||
|
||||
( async function() {
|
||||
>( async function() { const value = await x;}() ) : Promise<void>
|
||||
@ -23,9 +23,9 @@ import x from './a';
|
||||
>async function() { const value = await x;} : () => Promise<void>
|
||||
|
||||
const value = await x;
|
||||
>value : unknown
|
||||
>await x : unknown
|
||||
>x : Promise<unknown>
|
||||
>value : {}
|
||||
>await x : {}
|
||||
>x : Promise<{}>
|
||||
|
||||
}() );
|
||||
|
||||
|
||||
@ -1,21 +1,21 @@
|
||||
=== tests/cases/conformance/es6/modules/a.ts ===
|
||||
const x = new Promise( ( resolve, reject ) => { resolve( {} ); } );
|
||||
>x : Promise<unknown>
|
||||
>new Promise( ( resolve, reject ) => { resolve( {} ); } ) : Promise<unknown>
|
||||
>x : Promise<{}>
|
||||
>new Promise( ( resolve, reject ) => { resolve( {} ); } ) : Promise<{}>
|
||||
>Promise : PromiseConstructor
|
||||
>( resolve, reject ) => { resolve( {} ); } : (resolve: (value: unknown) => void, reject: (reason?: any) => void) => void
|
||||
>resolve : (value: unknown) => void
|
||||
>( resolve, reject ) => { resolve( {} ); } : (resolve: (value: {} | PromiseLike<{}>) => void, reject: (reason?: any) => void) => void
|
||||
>resolve : (value: {} | PromiseLike<{}>) => void
|
||||
>reject : (reason?: any) => void
|
||||
>resolve( {} ) : void
|
||||
>resolve : (value: unknown) => void
|
||||
>resolve : (value: {} | PromiseLike<{}>) => void
|
||||
>{} : {}
|
||||
|
||||
export default x;
|
||||
>x : Promise<unknown>
|
||||
>x : Promise<{}>
|
||||
|
||||
=== tests/cases/conformance/es6/modules/b.ts ===
|
||||
import x from './a';
|
||||
>x : Promise<unknown>
|
||||
>x : Promise<{}>
|
||||
|
||||
( async function() {
|
||||
>( async function() { const value = await x;}() ) : Promise<void>
|
||||
@ -23,9 +23,9 @@ import x from './a';
|
||||
>async function() { const value = await x;} : () => Promise<void>
|
||||
|
||||
const value = await x;
|
||||
>value : unknown
|
||||
>await x : unknown
|
||||
>x : Promise<unknown>
|
||||
>value : {}
|
||||
>await x : {}
|
||||
>x : Promise<{}>
|
||||
|
||||
}() );
|
||||
|
||||
|
||||
@ -29,15 +29,15 @@ export class BrokenClass {
|
||||
>[] : undefined[]
|
||||
|
||||
let populateItems = (order) => {
|
||||
>populateItems : (order: any) => Promise<unknown>
|
||||
>(order) => { return new Promise((resolve, reject) => { this.doStuff(order.id) .then((items) => { order.items = items; resolve(order); }); }); } : (order: any) => Promise<unknown>
|
||||
>populateItems : (order: any) => Promise<any>
|
||||
>(order) => { return new Promise((resolve, reject) => { this.doStuff(order.id) .then((items) => { order.items = items; resolve(order); }); }); } : (order: any) => Promise<any>
|
||||
>order : any
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
>new Promise((resolve, reject) => { this.doStuff(order.id) .then((items) => { order.items = items; resolve(order); }); }) : Promise<unknown>
|
||||
>new Promise((resolve, reject) => { this.doStuff(order.id) .then((items) => { order.items = items; resolve(order); }); }) : Promise<any>
|
||||
>Promise : PromiseConstructor
|
||||
>(resolve, reject) => { this.doStuff(order.id) .then((items) => { order.items = items; resolve(order); }); } : (resolve: (value: unknown) => void, reject: (reason?: any) => void) => void
|
||||
>resolve : (value: unknown) => void
|
||||
>(resolve, reject) => { this.doStuff(order.id) .then((items) => { order.items = items; resolve(order); }); } : (resolve: (value: any) => void, reject: (reason?: any) => void) => void
|
||||
>resolve : (value: any) => void
|
||||
>reject : (reason?: any) => void
|
||||
|
||||
this.doStuff(order.id)
|
||||
@ -65,7 +65,7 @@ export class BrokenClass {
|
||||
|
||||
resolve(order);
|
||||
>resolve(order) : void
|
||||
>resolve : (value: unknown) => void
|
||||
>resolve : (value: any) => void
|
||||
>order : any
|
||||
|
||||
});
|
||||
@ -74,19 +74,19 @@ export class BrokenClass {
|
||||
|
||||
return Promise.all(result.map(populateItems))
|
||||
>Promise.all(result.map(populateItems)) .then((orders: Array<MyModule.MyModel>) => { resolve(orders); }) : Promise<void>
|
||||
>Promise.all(result.map(populateItems)) .then : <TResult1 = unknown[], TResult2 = never>(onfulfilled?: (value: unknown[]) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>) => Promise<TResult1 | TResult2>
|
||||
>Promise.all(result.map(populateItems)) : Promise<unknown[]>
|
||||
>Promise.all(result.map(populateItems)) .then : <TResult1 = any[], TResult2 = never>(onfulfilled?: (value: any[]) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>) => Promise<TResult1 | TResult2>
|
||||
>Promise.all(result.map(populateItems)) : Promise<any[]>
|
||||
>Promise.all : { <T>(values: Iterable<T | PromiseLike<T>>): Promise<T[]>; <T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>, T9 | PromiseLike<T9>, T10 | PromiseLike<T10>]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]>; <T1, T2, T3, T4, T5, T6, T7, T8, T9>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>, T9 | PromiseLike<T9>]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9]>; <T1, T2, T3, T4, T5, T6, T7, T8>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8]>; <T1, T2, T3, T4, T5, T6, T7>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>]): Promise<[T1, T2, T3, T4, T5, T6, T7]>; <T1, T2, T3, T4, T5, T6>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>]): Promise<[T1, T2, T3, T4, T5, T6]>; <T1, T2, T3, T4, T5>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>]): Promise<[T1, T2, T3, T4, T5]>; <T1, T2, T3, T4>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>]): Promise<[T1, T2, T3, T4]>; <T1, T2, T3>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>]): Promise<[T1, T2, T3]>; <T1, T2>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>]): Promise<[T1, T2]>; <T>(values: readonly (T | PromiseLike<T>)[]): Promise<T[]>; }
|
||||
>Promise : PromiseConstructor
|
||||
>all : { <T>(values: Iterable<T | PromiseLike<T>>): Promise<T[]>; <T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>, T9 | PromiseLike<T9>, T10 | PromiseLike<T10>]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]>; <T1, T2, T3, T4, T5, T6, T7, T8, T9>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>, T9 | PromiseLike<T9>]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9]>; <T1, T2, T3, T4, T5, T6, T7, T8>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8]>; <T1, T2, T3, T4, T5, T6, T7>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>]): Promise<[T1, T2, T3, T4, T5, T6, T7]>; <T1, T2, T3, T4, T5, T6>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>]): Promise<[T1, T2, T3, T4, T5, T6]>; <T1, T2, T3, T4, T5>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>]): Promise<[T1, T2, T3, T4, T5]>; <T1, T2, T3, T4>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>]): Promise<[T1, T2, T3, T4]>; <T1, T2, T3>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>]): Promise<[T1, T2, T3]>; <T1, T2>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>]): Promise<[T1, T2]>; <T>(values: readonly (T | PromiseLike<T>)[]): Promise<T[]>; }
|
||||
>result.map(populateItems) : Promise<unknown>[]
|
||||
>result.map(populateItems) : Promise<any>[]
|
||||
>result.map : <U>(callbackfn: (value: MyModule.MyModel, index: number, array: MyModule.MyModel[]) => U, thisArg?: any) => U[]
|
||||
>result : MyModule.MyModel[]
|
||||
>map : <U>(callbackfn: (value: MyModule.MyModel, index: number, array: MyModule.MyModel[]) => U, thisArg?: any) => U[]
|
||||
>populateItems : (order: any) => Promise<unknown>
|
||||
>populateItems : (order: any) => Promise<any>
|
||||
|
||||
.then((orders: Array<MyModule.MyModel>) => {
|
||||
>then : <TResult1 = unknown[], TResult2 = never>(onfulfilled?: (value: unknown[]) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>) => Promise<TResult1 | TResult2>
|
||||
>then : <TResult1 = any[], TResult2 = never>(onfulfilled?: (value: any[]) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>) => Promise<TResult1 | TResult2>
|
||||
>(orders: Array<MyModule.MyModel>) => { resolve(orders); } : (orders: Array<MyModule.MyModel>) => void
|
||||
>orders : MyModule.MyModel[]
|
||||
>MyModule : any
|
||||
|
||||
110
tests/baselines/reference/revealingConstructorInference.symbols
Normal file
110
tests/baselines/reference/revealingConstructorInference.symbols
Normal file
@ -0,0 +1,110 @@
|
||||
=== tests/cases/conformance/types/typeRelationships/typeInference/revealingConstructorInference.ts ===
|
||||
// uncalled
|
||||
const p0 = new Promise(resolve => {});
|
||||
>p0 : Symbol(p0, Decl(revealingConstructorInference.ts, 1, 5))
|
||||
>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, --, --))
|
||||
>resolve : Symbol(resolve, Decl(revealingConstructorInference.ts, 1, 23))
|
||||
|
||||
// called with no argument
|
||||
const p1 = new Promise(resolve => resolve());
|
||||
>p1 : Symbol(p1, Decl(revealingConstructorInference.ts, 4, 5))
|
||||
>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, --, --))
|
||||
>resolve : Symbol(resolve, Decl(revealingConstructorInference.ts, 4, 23))
|
||||
>resolve : Symbol(resolve, Decl(revealingConstructorInference.ts, 4, 23))
|
||||
|
||||
// called with argument
|
||||
const p2 = new Promise(resolve => resolve(1));
|
||||
>p2 : Symbol(p2, Decl(revealingConstructorInference.ts, 7, 5))
|
||||
>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, --, --))
|
||||
>resolve : Symbol(resolve, Decl(revealingConstructorInference.ts, 7, 23))
|
||||
>resolve : Symbol(resolve, Decl(revealingConstructorInference.ts, 7, 23))
|
||||
|
||||
// called with promise-like argument
|
||||
const p3 = new Promise(resolve => resolve(Promise.resolve(1)));
|
||||
>p3 : Symbol(p3, Decl(revealingConstructorInference.ts, 10, 5))
|
||||
>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, --, --))
|
||||
>resolve : Symbol(resolve, Decl(revealingConstructorInference.ts, 10, 23))
|
||||
>resolve : Symbol(resolve, Decl(revealingConstructorInference.ts, 10, 23))
|
||||
>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.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, --, --))
|
||||
>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
|
||||
|
||||
// called with multiple arguments
|
||||
const p4 = new Promise(resolve => {
|
||||
>p4 : Symbol(p4, Decl(revealingConstructorInference.ts, 13, 5))
|
||||
>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, --, --))
|
||||
>resolve : Symbol(resolve, Decl(revealingConstructorInference.ts, 13, 23))
|
||||
|
||||
resolve(1);
|
||||
>resolve : Symbol(resolve, Decl(revealingConstructorInference.ts, 13, 23))
|
||||
|
||||
resolve("a");
|
||||
>resolve : Symbol(resolve, Decl(revealingConstructorInference.ts, 13, 23))
|
||||
|
||||
});
|
||||
|
||||
// called with multiple arguments (mix of non-promise and PromiseLike)
|
||||
const p5 = new Promise(resolve => {
|
||||
>p5 : Symbol(p5, Decl(revealingConstructorInference.ts, 19, 5))
|
||||
>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, --, --))
|
||||
>resolve : Symbol(resolve, Decl(revealingConstructorInference.ts, 19, 23))
|
||||
|
||||
resolve(1);
|
||||
>resolve : Symbol(resolve, Decl(revealingConstructorInference.ts, 19, 23))
|
||||
|
||||
resolve(Promise.resolve("a"));
|
||||
>resolve : Symbol(resolve, Decl(revealingConstructorInference.ts, 19, 23))
|
||||
>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.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, --, --))
|
||||
>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
|
||||
|
||||
});
|
||||
|
||||
// called with argument in nested callback
|
||||
declare function soon(f: () => void): void;
|
||||
>soon : Symbol(soon, Decl(revealingConstructorInference.ts, 22, 3))
|
||||
>f : Symbol(f, Decl(revealingConstructorInference.ts, 25, 22))
|
||||
|
||||
const p6 = new Promise(resolve => {
|
||||
>p6 : Symbol(p6, Decl(revealingConstructorInference.ts, 26, 5))
|
||||
>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, --, --))
|
||||
>resolve : Symbol(resolve, Decl(revealingConstructorInference.ts, 26, 23))
|
||||
|
||||
soon(() => resolve(1));
|
||||
>soon : Symbol(soon, Decl(revealingConstructorInference.ts, 22, 3))
|
||||
>resolve : Symbol(resolve, Decl(revealingConstructorInference.ts, 26, 23))
|
||||
|
||||
});
|
||||
|
||||
// callback passed to another function
|
||||
declare function resolveWith<T>(f: (value: T) => void, value: T): void;
|
||||
>resolveWith : Symbol(resolveWith, Decl(revealingConstructorInference.ts, 28, 3))
|
||||
>T : Symbol(T, Decl(revealingConstructorInference.ts, 31, 29))
|
||||
>f : Symbol(f, Decl(revealingConstructorInference.ts, 31, 32))
|
||||
>value : Symbol(value, Decl(revealingConstructorInference.ts, 31, 36))
|
||||
>T : Symbol(T, Decl(revealingConstructorInference.ts, 31, 29))
|
||||
>value : Symbol(value, Decl(revealingConstructorInference.ts, 31, 54))
|
||||
>T : Symbol(T, Decl(revealingConstructorInference.ts, 31, 29))
|
||||
|
||||
const p7 = new Promise(resolve => resolveWith(resolve, 1));
|
||||
>p7 : Symbol(p7, Decl(revealingConstructorInference.ts, 32, 5))
|
||||
>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, --, --))
|
||||
>resolve : Symbol(resolve, Decl(revealingConstructorInference.ts, 32, 23))
|
||||
>resolveWith : Symbol(resolveWith, Decl(revealingConstructorInference.ts, 28, 3))
|
||||
>resolve : Symbol(resolve, Decl(revealingConstructorInference.ts, 32, 23))
|
||||
|
||||
// lower priority inference
|
||||
const enum E { zero = 0 }
|
||||
>E : Symbol(E, Decl(revealingConstructorInference.ts, 32, 59))
|
||||
>zero : Symbol(E.zero, Decl(revealingConstructorInference.ts, 35, 14))
|
||||
|
||||
const p8: Promise<number> = new Promise(resolve => resolve(E.zero));
|
||||
>p8 : Symbol(p8, Decl(revealingConstructorInference.ts, 36, 5))
|
||||
>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, --, --))
|
||||
>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, --, --))
|
||||
>resolve : Symbol(resolve, Decl(revealingConstructorInference.ts, 36, 40))
|
||||
>resolve : Symbol(resolve, Decl(revealingConstructorInference.ts, 36, 40))
|
||||
>E.zero : Symbol(E.zero, Decl(revealingConstructorInference.ts, 35, 14))
|
||||
>E : Symbol(E, Decl(revealingConstructorInference.ts, 32, 59))
|
||||
>zero : Symbol(E.zero, Decl(revealingConstructorInference.ts, 35, 14))
|
||||
|
||||
147
tests/baselines/reference/revealingConstructorInference.types
Normal file
147
tests/baselines/reference/revealingConstructorInference.types
Normal file
@ -0,0 +1,147 @@
|
||||
=== tests/cases/conformance/types/typeRelationships/typeInference/revealingConstructorInference.ts ===
|
||||
// uncalled
|
||||
const p0 = new Promise(resolve => {});
|
||||
>p0 : Promise<unknown>
|
||||
>new Promise(resolve => {}) : Promise<unknown>
|
||||
>Promise : PromiseConstructor
|
||||
>resolve => {} : (resolve: (value: unknown) => void) => void
|
||||
>resolve : (value: unknown) => void
|
||||
|
||||
// called with no argument
|
||||
const p1 = new Promise(resolve => resolve());
|
||||
>p1 : Promise<void>
|
||||
>new Promise(resolve => resolve()) : Promise<void>
|
||||
>Promise : PromiseConstructor
|
||||
>resolve => resolve() : (resolve: (value: void | PromiseLike<void>) => void) => void
|
||||
>resolve : (value: void | PromiseLike<void>) => void
|
||||
>resolve() : void
|
||||
>resolve : (value: void | PromiseLike<void>) => void
|
||||
|
||||
// called with argument
|
||||
const p2 = new Promise(resolve => resolve(1));
|
||||
>p2 : Promise<number>
|
||||
>new Promise(resolve => resolve(1)) : Promise<number>
|
||||
>Promise : PromiseConstructor
|
||||
>resolve => resolve(1) : (resolve: (value: number | PromiseLike<number>) => void) => void
|
||||
>resolve : (value: number | PromiseLike<number>) => void
|
||||
>resolve(1) : void
|
||||
>resolve : (value: number | PromiseLike<number>) => void
|
||||
>1 : 1
|
||||
|
||||
// called with promise-like argument
|
||||
const p3 = new Promise(resolve => resolve(Promise.resolve(1)));
|
||||
>p3 : Promise<number>
|
||||
>new Promise(resolve => resolve(Promise.resolve(1))) : Promise<number>
|
||||
>Promise : PromiseConstructor
|
||||
>resolve => resolve(Promise.resolve(1)) : (resolve: (value: number | PromiseLike<number>) => void) => any
|
||||
>resolve : (value: number | PromiseLike<number>) => void
|
||||
>resolve(Promise.resolve(1)) : void
|
||||
>resolve : (value: number | PromiseLike<number>) => void
|
||||
>Promise.resolve(1) : Promise<number>
|
||||
>Promise.resolve : { (): Promise<void>; <T>(value: T | PromiseLike<T>): Promise<T>; }
|
||||
>Promise : PromiseConstructor
|
||||
>resolve : { (): Promise<void>; <T>(value: T | PromiseLike<T>): Promise<T>; }
|
||||
>1 : 1
|
||||
|
||||
// called with multiple arguments
|
||||
const p4 = new Promise(resolve => {
|
||||
>p4 : Promise<string | number>
|
||||
>new Promise(resolve => { resolve(1); resolve("a");}) : Promise<string | number>
|
||||
>Promise : PromiseConstructor
|
||||
>resolve => { resolve(1); resolve("a");} : (resolve: (value: string | number | PromiseLike<string | number>) => void) => void
|
||||
>resolve : (value: string | number | PromiseLike<string | number>) => void
|
||||
|
||||
resolve(1);
|
||||
>resolve(1) : void
|
||||
>resolve : (value: string | number | PromiseLike<string | number>) => void
|
||||
>1 : 1
|
||||
|
||||
resolve("a");
|
||||
>resolve("a") : void
|
||||
>resolve : (value: string | number | PromiseLike<string | number>) => void
|
||||
>"a" : "a"
|
||||
|
||||
});
|
||||
|
||||
// called with multiple arguments (mix of non-promise and PromiseLike)
|
||||
const p5 = new Promise(resolve => {
|
||||
>p5 : Promise<string | number>
|
||||
>new Promise(resolve => { resolve(1); resolve(Promise.resolve("a"));}) : Promise<string | number>
|
||||
>Promise : PromiseConstructor
|
||||
>resolve => { resolve(1); resolve(Promise.resolve("a"));} : (resolve: (value: string | number | PromiseLike<string | number>) => void) => void
|
||||
>resolve : (value: string | number | PromiseLike<string | number>) => void
|
||||
|
||||
resolve(1);
|
||||
>resolve(1) : void
|
||||
>resolve : (value: string | number | PromiseLike<string | number>) => void
|
||||
>1 : 1
|
||||
|
||||
resolve(Promise.resolve("a"));
|
||||
>resolve(Promise.resolve("a")) : void
|
||||
>resolve : (value: string | number | PromiseLike<string | number>) => void
|
||||
>Promise.resolve("a") : Promise<string>
|
||||
>Promise.resolve : { (): Promise<void>; <T>(value: T | PromiseLike<T>): Promise<T>; }
|
||||
>Promise : PromiseConstructor
|
||||
>resolve : { (): Promise<void>; <T>(value: T | PromiseLike<T>): Promise<T>; }
|
||||
>"a" : "a"
|
||||
|
||||
});
|
||||
|
||||
// called with argument in nested callback
|
||||
declare function soon(f: () => void): void;
|
||||
>soon : (f: () => void) => void
|
||||
>f : () => void
|
||||
|
||||
const p6 = new Promise(resolve => {
|
||||
>p6 : Promise<number>
|
||||
>new Promise(resolve => { soon(() => resolve(1));}) : Promise<number>
|
||||
>Promise : PromiseConstructor
|
||||
>resolve => { soon(() => resolve(1));} : (resolve: (value: number | PromiseLike<number>) => void) => void
|
||||
>resolve : (value: number | PromiseLike<number>) => void
|
||||
|
||||
soon(() => resolve(1));
|
||||
>soon(() => resolve(1)) : void
|
||||
>soon : (f: () => void) => void
|
||||
>() => resolve(1) : () => void
|
||||
>resolve(1) : void
|
||||
>resolve : (value: number | PromiseLike<number>) => void
|
||||
>1 : 1
|
||||
|
||||
});
|
||||
|
||||
// callback passed to another function
|
||||
declare function resolveWith<T>(f: (value: T) => void, value: T): void;
|
||||
>resolveWith : <T>(f: (value: T) => void, value: T) => void
|
||||
>f : (value: T) => void
|
||||
>value : T
|
||||
>value : T
|
||||
|
||||
const p7 = new Promise(resolve => resolveWith(resolve, 1));
|
||||
>p7 : Promise<number>
|
||||
>new Promise(resolve => resolveWith(resolve, 1)) : Promise<number>
|
||||
>Promise : PromiseConstructor
|
||||
>resolve => resolveWith(resolve, 1) : (resolve: (value: number | PromiseLike<number>) => void) => void
|
||||
>resolve : (value: number | PromiseLike<number>) => void
|
||||
>resolveWith(resolve, 1) : void
|
||||
>resolveWith : <T>(f: (value: T) => void, value: T) => void
|
||||
>resolve : (value: number | PromiseLike<number>) => void
|
||||
>1 : 1
|
||||
|
||||
// lower priority inference
|
||||
const enum E { zero = 0 }
|
||||
>E : E
|
||||
>zero : E.zero
|
||||
>0 : 0
|
||||
|
||||
const p8: Promise<number> = new Promise(resolve => resolve(E.zero));
|
||||
>p8 : Promise<number>
|
||||
>new Promise(resolve => resolve(E.zero)) : Promise<number>
|
||||
>Promise : PromiseConstructor
|
||||
>resolve => resolve(E.zero) : (resolve: (value: number | PromiseLike<number>) => void) => void
|
||||
>resolve : (value: number | PromiseLike<number>) => void
|
||||
>resolve(E.zero) : void
|
||||
>resolve : (value: number | PromiseLike<number>) => void
|
||||
>E.zero : E
|
||||
>E : typeof E
|
||||
>zero : E
|
||||
|
||||
@ -0,0 +1,40 @@
|
||||
// @target: esnext
|
||||
// @noEmit: true
|
||||
|
||||
// uncalled
|
||||
const p0 = new Promise(resolve => {});
|
||||
|
||||
// called with no argument
|
||||
const p1 = new Promise(resolve => resolve());
|
||||
|
||||
// called with argument
|
||||
const p2 = new Promise(resolve => resolve(1));
|
||||
|
||||
// called with promise-like argument
|
||||
const p3 = new Promise(resolve => resolve(Promise.resolve(1)));
|
||||
|
||||
// called with multiple arguments
|
||||
const p4 = new Promise(resolve => {
|
||||
resolve(1);
|
||||
resolve("a");
|
||||
});
|
||||
|
||||
// called with multiple arguments (mix of non-promise and PromiseLike)
|
||||
const p5 = new Promise(resolve => {
|
||||
resolve(1);
|
||||
resolve(Promise.resolve("a"));
|
||||
});
|
||||
|
||||
// called with argument in nested callback
|
||||
declare function soon(f: () => void): void;
|
||||
const p6 = new Promise(resolve => {
|
||||
soon(() => resolve(1));
|
||||
});
|
||||
|
||||
// callback passed to another function
|
||||
declare function resolveWith<T>(f: (value: T) => void, value: T): void;
|
||||
const p7 = new Promise(resolve => resolveWith(resolve, 1));
|
||||
|
||||
// lower priority inference
|
||||
const enum E { zero = 0 }
|
||||
const p8: Promise<number> = new Promise(resolve => resolve(E.zero));
|
||||
Loading…
x
Reference in New Issue
Block a user