|
|
|
|
@@ -4117,7 +4117,7 @@ namespace ts {
|
|
|
|
|
// This elementType will be used if the specific property corresponding to this index is not
|
|
|
|
|
// present (aka the tuple element property). This call also checks that the parentType is in
|
|
|
|
|
// fact an iterable or array (depending on target language).
|
|
|
|
|
const elementType = checkIteratedTypeOrElementType(parentType, pattern, /*allowStringInput*/ false, /*allowAsyncIterable*/ false);
|
|
|
|
|
const elementType = checkIteratedTypeOrElementType(parentType, pattern, /*allowStringInput*/ false, /*allowAsyncIterables*/ false);
|
|
|
|
|
if (declaration.dotDotDotToken) {
|
|
|
|
|
// Rest element has an array type with the same element type as the parent type
|
|
|
|
|
type = createArrayType(elementType);
|
|
|
|
|
@@ -10888,12 +10888,12 @@ namespace ts {
|
|
|
|
|
|
|
|
|
|
function getTypeOfDestructuredArrayElement(type: Type, index: number) {
|
|
|
|
|
return isTupleLikeType(type) && getTypeOfPropertyOfType(type, "" + index) ||
|
|
|
|
|
checkIteratedTypeOrElementType(type, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterable*/ false) ||
|
|
|
|
|
checkIteratedTypeOrElementType(type, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterables*/ false) ||
|
|
|
|
|
unknownType;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getTypeOfDestructuredSpreadExpression(type: Type) {
|
|
|
|
|
return createArrayType(checkIteratedTypeOrElementType(type, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterable*/ false) || unknownType);
|
|
|
|
|
return createArrayType(checkIteratedTypeOrElementType(type, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterables*/ false) || unknownType);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getAssignedTypeOfBinaryExpression(node: BinaryExpression): Type {
|
|
|
|
|
@@ -12867,7 +12867,7 @@ namespace ts {
|
|
|
|
|
const index = indexOf(arrayLiteral.elements, node);
|
|
|
|
|
return getTypeOfPropertyOfContextualType(type, "" + index)
|
|
|
|
|
|| getIndexTypeOfContextualType(type, IndexKind.Number)
|
|
|
|
|
|| getIteratedTypeOrElementType(type, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterable*/ false, /*checkAssignability*/ false);
|
|
|
|
|
|| getIteratedTypeOrElementType(type, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterables*/ false, /*checkAssignability*/ false);
|
|
|
|
|
}
|
|
|
|
|
return undefined;
|
|
|
|
|
}
|
|
|
|
|
@@ -13105,7 +13105,7 @@ namespace ts {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const arrayOrIterableType = checkExpression(node.expression, checkMode);
|
|
|
|
|
return checkIteratedTypeOrElementType(arrayOrIterableType, node.expression, /*allowStringInput*/ false, /*allowAsyncIterable*/ false);
|
|
|
|
|
return checkIteratedTypeOrElementType(arrayOrIterableType, node.expression, /*allowStringInput*/ false, /*allowAsyncIterables*/ false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function hasDefaultValue(node: BindingElement | Expression): boolean {
|
|
|
|
|
@@ -13134,7 +13134,7 @@ namespace ts {
|
|
|
|
|
// if there is no index type / iterated type.
|
|
|
|
|
const restArrayType = checkExpression((<SpreadElement>e).expression, checkMode);
|
|
|
|
|
const restElementType = getIndexTypeOfType(restArrayType, IndexKind.Number) ||
|
|
|
|
|
getIteratedTypeOrElementType(restArrayType, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterable*/ false, /*checkAssignability*/ false);
|
|
|
|
|
getIteratedTypeOrElementType(restArrayType, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterables*/ false, /*checkAssignability*/ false);
|
|
|
|
|
if (restElementType) {
|
|
|
|
|
elementTypes.push(restElementType);
|
|
|
|
|
}
|
|
|
|
|
@@ -16987,7 +16987,7 @@ namespace ts {
|
|
|
|
|
// This elementType will be used if the specific property corresponding to this index is not
|
|
|
|
|
// present (aka the tuple element property). This call also checks that the parentType is in
|
|
|
|
|
// fact an iterable or array (depending on target language).
|
|
|
|
|
const elementType = checkIteratedTypeOrElementType(sourceType, node, /*allowStringInput*/ false, /*allowAsyncIterable*/ false) || unknownType;
|
|
|
|
|
const elementType = checkIteratedTypeOrElementType(sourceType, node, /*allowStringInput*/ false, /*allowAsyncIterables*/ false) || unknownType;
|
|
|
|
|
const elements = node.elements;
|
|
|
|
|
for (let i = 0; i < elements.length; i++) {
|
|
|
|
|
checkArrayLiteralDestructuringElementAssignment(node, sourceType, i, elementType, checkMode);
|
|
|
|
|
@@ -20131,12 +20131,12 @@ namespace ts {
|
|
|
|
|
return checkIteratedTypeOrElementType(expressionType, rhsExpression, /*allowStringInput*/ true, awaitModifier !== undefined);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function checkIteratedTypeOrElementType(inputType: Type, errorNode: Node, allowStringInput: boolean, allowAsyncIterable: boolean): Type {
|
|
|
|
|
function checkIteratedTypeOrElementType(inputType: Type, errorNode: Node, allowStringInput: boolean, allowAsyncIterables: boolean): Type {
|
|
|
|
|
if (isTypeAny(inputType)) {
|
|
|
|
|
return inputType;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return getIteratedTypeOrElementType(inputType, errorNode, allowStringInput, allowAsyncIterable, /*checkAssignability*/ true) || anyType;
|
|
|
|
|
return getIteratedTypeOrElementType(inputType, errorNode, allowStringInput, allowAsyncIterables, /*checkAssignability*/ true) || anyType;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -20144,16 +20144,16 @@ namespace ts {
|
|
|
|
|
* we want to get the iterated type of an iterable for ES2015 or later, or the iterated type
|
|
|
|
|
* of a iterable (if defined globally) or element type of an array like for ES2015 or earlier.
|
|
|
|
|
*/
|
|
|
|
|
function getIteratedTypeOrElementType(inputType: Type, errorNode: Node, allowStringInput: boolean, allowAsyncIterable: boolean, checkAssignability: boolean): Type {
|
|
|
|
|
function getIteratedTypeOrElementType(inputType: Type, errorNode: Node, allowStringInput: boolean, allowAsyncIterables: boolean, checkAssignability: boolean): Type {
|
|
|
|
|
const uplevelIteration = languageVersion >= ScriptTarget.ES2015;
|
|
|
|
|
const downlevelIteration = !uplevelIteration && compilerOptions.downlevelIteration;
|
|
|
|
|
|
|
|
|
|
// Get the iterated type of an `Iterable<T>` or `IterableIterator<T>` only in ES2015
|
|
|
|
|
// or higher, when inside of an async generator or for-await-if, or when
|
|
|
|
|
// downlevelIteration is requested.
|
|
|
|
|
if (uplevelIteration || downlevelIteration || allowAsyncIterable) {
|
|
|
|
|
if (uplevelIteration || downlevelIteration || allowAsyncIterables) {
|
|
|
|
|
// We only report errors for an invalid iterable type in ES2015 or higher.
|
|
|
|
|
const iteratedType = getIteratedTypeOfIterable(inputType, uplevelIteration ? errorNode : undefined, allowAsyncIterable, allowAsyncIterable, checkAssignability);
|
|
|
|
|
const iteratedType = getIteratedTypeOfIterable(inputType, uplevelIteration ? errorNode : undefined, allowAsyncIterables, /*allowSyncIterables*/ true, checkAssignability);
|
|
|
|
|
if (iteratedType || uplevelIteration) {
|
|
|
|
|
return iteratedType;
|
|
|
|
|
}
|
|
|
|
|
@@ -20267,79 +20267,75 @@ namespace ts {
|
|
|
|
|
* For a **for-await-of** statement or a `yield*` in an async generator we will look for
|
|
|
|
|
* the `[Symbol.asyncIterator]()` method first, and then the `[Symbol.iterator]()` method.
|
|
|
|
|
*/
|
|
|
|
|
function getIteratedTypeOfIterable(type: Type, errorNode: Node | undefined, isAsyncIterable: boolean, allowNonAsyncIterables: boolean, checkAssignability: boolean): Type | undefined {
|
|
|
|
|
function getIteratedTypeOfIterable(type: Type, errorNode: Node | undefined, allowAsyncIterables: boolean, allowSyncIterables: boolean, checkAssignability: boolean): Type | undefined {
|
|
|
|
|
if (isTypeAny(type)) {
|
|
|
|
|
return undefined;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const typeAsIterable = <IterableOrIteratorType>type;
|
|
|
|
|
if (isAsyncIterable ? typeAsIterable.iteratedTypeOfAsyncIterable : typeAsIterable.iteratedTypeOfIterable) {
|
|
|
|
|
return isAsyncIterable ? typeAsIterable.iteratedTypeOfAsyncIterable : typeAsIterable.iteratedTypeOfIterable;
|
|
|
|
|
}
|
|
|
|
|
return mapType(type, getIteratedType);
|
|
|
|
|
|
|
|
|
|
if (isAsyncIterable) {
|
|
|
|
|
// As an optimization, if the type is an instantiation of the global `AsyncIterable<T>`
|
|
|
|
|
// or the global `AsyncIterableIterator<T>` then just grab its type argument.
|
|
|
|
|
if (isReferenceToType(type, getGlobalAsyncIterableType(/*reportErrors*/ false)) ||
|
|
|
|
|
isReferenceToType(type, getGlobalAsyncIterableIteratorType(/*reportErrors*/ false))) {
|
|
|
|
|
return typeAsIterable.iteratedTypeOfAsyncIterable = (<GenericType>type).typeArguments[0];
|
|
|
|
|
function getIteratedType(type: Type) {
|
|
|
|
|
const typeAsIterable = <IterableOrIteratorType>type;
|
|
|
|
|
if (allowAsyncIterables) {
|
|
|
|
|
if (typeAsIterable.iteratedTypeOfAsyncIterable) {
|
|
|
|
|
return typeAsIterable.iteratedTypeOfAsyncIterable;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// As an optimization, if the type is an instantiation of the global `AsyncIterable<T>`
|
|
|
|
|
// or the global `AsyncIterableIterator<T>` then just grab its type argument.
|
|
|
|
|
if (isReferenceToType(type, getGlobalAsyncIterableType(/*reportErrors*/ false)) ||
|
|
|
|
|
isReferenceToType(type, getGlobalAsyncIterableIteratorType(/*reportErrors*/ false))) {
|
|
|
|
|
return typeAsIterable.iteratedTypeOfAsyncIterable = (<GenericType>type).typeArguments[0];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!isAsyncIterable || allowNonAsyncIterables) {
|
|
|
|
|
// As an optimization, if the type is an instantiation of the global `Iterable<T>` or
|
|
|
|
|
// `IterableIterator<T>` then just grab its type argument.
|
|
|
|
|
if (isReferenceToType(type, getGlobalIterableType(/*reportErrors*/ false)) ||
|
|
|
|
|
isReferenceToType(type, getGlobalIterableIteratorType(/*reportErrors*/ false))) {
|
|
|
|
|
return isAsyncIterable
|
|
|
|
|
? typeAsIterable.iteratedTypeOfAsyncIterable = (<GenericType>type).typeArguments[0]
|
|
|
|
|
: typeAsIterable.iteratedTypeOfIterable = (<GenericType>type).typeArguments[0];
|
|
|
|
|
if (allowSyncIterables) {
|
|
|
|
|
if (typeAsIterable.iteratedTypeOfIterable) {
|
|
|
|
|
return typeAsIterable.iteratedTypeOfIterable;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// As an optimization, if the type is an instantiation of the global `Iterable<T>` or
|
|
|
|
|
// `IterableIterator<T>` then just grab its type argument.
|
|
|
|
|
if (isReferenceToType(type, getGlobalIterableType(/*reportErrors*/ false)) ||
|
|
|
|
|
isReferenceToType(type, getGlobalIterableIteratorType(/*reportErrors*/ false))) {
|
|
|
|
|
return typeAsIterable.iteratedTypeOfIterable = (<GenericType>type).typeArguments[0];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let iteratorMethodSignatures: Signature[];
|
|
|
|
|
let isNonAsyncIterable = false;
|
|
|
|
|
if (isAsyncIterable) {
|
|
|
|
|
const iteratorMethod = getTypeOfPropertyOfType(type, getPropertyNameForKnownSymbolName("asyncIterator"));
|
|
|
|
|
if (isTypeAny(iteratorMethod)) {
|
|
|
|
|
const asyncMethodType = allowAsyncIterables && getTypeOfPropertyOfType(type, getPropertyNameForKnownSymbolName("asyncIterator"));
|
|
|
|
|
const methodType = asyncMethodType || (allowSyncIterables && getTypeOfPropertyOfType(type, getPropertyNameForKnownSymbolName("iterator")));
|
|
|
|
|
if (isTypeAny(methodType)) {
|
|
|
|
|
return undefined;
|
|
|
|
|
}
|
|
|
|
|
iteratorMethodSignatures = iteratorMethod && getSignaturesOfType(iteratorMethod, SignatureKind.Call);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!isAsyncIterable || (allowNonAsyncIterables && !some(iteratorMethodSignatures))) {
|
|
|
|
|
const iteratorMethod = getTypeOfPropertyOfType(type, getPropertyNameForKnownSymbolName("iterator"));
|
|
|
|
|
if (isTypeAny(iteratorMethod)) {
|
|
|
|
|
const signatures = methodType && getSignaturesOfType(methodType, SignatureKind.Call);
|
|
|
|
|
if (!some(signatures)) {
|
|
|
|
|
if (errorNode) {
|
|
|
|
|
error(errorNode,
|
|
|
|
|
allowAsyncIterables
|
|
|
|
|
? Diagnostics.Type_must_have_a_Symbol_asyncIterator_method_that_returns_an_async_iterator
|
|
|
|
|
: Diagnostics.Type_must_have_a_Symbol_iterator_method_that_returns_an_iterator);
|
|
|
|
|
// only report on the first error
|
|
|
|
|
errorNode = undefined;
|
|
|
|
|
}
|
|
|
|
|
return undefined;
|
|
|
|
|
}
|
|
|
|
|
iteratorMethodSignatures = iteratorMethod && getSignaturesOfType(iteratorMethod, SignatureKind.Call);
|
|
|
|
|
isNonAsyncIterable = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (some(iteratorMethodSignatures)) {
|
|
|
|
|
const iteratorMethodReturnType = getUnionType(map(iteratorMethodSignatures, getReturnTypeOfSignature), /*subtypeReduction*/ true);
|
|
|
|
|
const iteratedType = getIteratedTypeOfIterator(iteratorMethodReturnType, errorNode, /*isAsyncIterator*/ !isNonAsyncIterable);
|
|
|
|
|
const returnType = getUnionType(map(signatures, getReturnTypeOfSignature), /*subtypeReduction*/ true);
|
|
|
|
|
const iteratedType = getIteratedTypeOfIterator(returnType, errorNode, /*isAsyncIterator*/ !!asyncMethodType);
|
|
|
|
|
if (checkAssignability && errorNode && iteratedType) {
|
|
|
|
|
// If `checkAssignability` was specified, we were called from
|
|
|
|
|
// `checkIteratedTypeOrElementType`. As such, we need to validate that
|
|
|
|
|
// the type passed in is actually an Iterable.
|
|
|
|
|
checkTypeAssignableTo(type, isNonAsyncIterable
|
|
|
|
|
? createIterableType(iteratedType)
|
|
|
|
|
: createAsyncIterableType(iteratedType), errorNode);
|
|
|
|
|
checkTypeAssignableTo(type, asyncMethodType
|
|
|
|
|
? createAsyncIterableType(iteratedType)
|
|
|
|
|
: createIterableType(iteratedType), errorNode);
|
|
|
|
|
}
|
|
|
|
|
return isAsyncIterable
|
|
|
|
|
|
|
|
|
|
return asyncMethodType
|
|
|
|
|
? typeAsIterable.iteratedTypeOfAsyncIterable = iteratedType
|
|
|
|
|
: typeAsIterable.iteratedTypeOfIterable = iteratedType;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (errorNode) {
|
|
|
|
|
error(errorNode,
|
|
|
|
|
isAsyncIterable
|
|
|
|
|
? Diagnostics.Type_must_have_a_Symbol_asyncIterator_method_that_returns_an_async_iterator
|
|
|
|
|
: Diagnostics.Type_must_have_a_Symbol_iterator_method_that_returns_an_iterator);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return undefined;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -20439,7 +20435,7 @@ namespace ts {
|
|
|
|
|
return undefined;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return getIteratedTypeOfIterable(returnType, /*errorNode*/ undefined, isAsyncGenerator, /*allowNonAsyncIterables*/ false, /*checkAssignability*/ false)
|
|
|
|
|
return getIteratedTypeOfIterable(returnType, /*errorNode*/ undefined, /*allowAsyncIterables*/ isAsyncGenerator, /*allowSyncIterables*/ !isAsyncGenerator, /*checkAssignability*/ false)
|
|
|
|
|
|| getIteratedTypeOfIterator(returnType, /*errorNode*/ undefined, isAsyncGenerator);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -21086,10 +21082,6 @@ namespace ts {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function isAccessor(kind: SyntaxKind): boolean {
|
|
|
|
|
return kind === SyntaxKind.GetAccessor || kind === SyntaxKind.SetAccessor;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function checkInheritedPropertiesAreIdentical(type: InterfaceType, typeNode: Node): boolean {
|
|
|
|
|
const baseTypes = getBaseTypes(type);
|
|
|
|
|
if (baseTypes.length < 2) {
|
|
|
|
|
@@ -22649,7 +22641,7 @@ namespace ts {
|
|
|
|
|
Debug.assert(expr.parent.kind === SyntaxKind.ArrayLiteralExpression);
|
|
|
|
|
// [{ property1: p1, property2 }] = elems;
|
|
|
|
|
const typeOfArrayLiteral = getTypeOfArrayLiteralOrObjectLiteralDestructuringAssignment(<Expression>expr.parent);
|
|
|
|
|
const elementType = checkIteratedTypeOrElementType(typeOfArrayLiteral || unknownType, expr.parent, /*allowStringInput*/ false, /*allowAsyncIterable*/ false) || unknownType;
|
|
|
|
|
const elementType = checkIteratedTypeOrElementType(typeOfArrayLiteral || unknownType, expr.parent, /*allowStringInput*/ false, /*allowAsyncIterables*/ false) || unknownType;
|
|
|
|
|
return checkArrayLiteralDestructuringElementAssignment(<ArrayLiteralExpression>expr.parent, typeOfArrayLiteral,
|
|
|
|
|
indexOf((<ArrayLiteralExpression>expr.parent).elements, expr), elementType || unknownType);
|
|
|
|
|
}
|
|
|
|
|
@@ -24559,7 +24551,7 @@ namespace ts {
|
|
|
|
|
function checkGrammarStatementInAmbientContext(node: Node): boolean {
|
|
|
|
|
if (isInAmbientContext(node)) {
|
|
|
|
|
// An accessors is already reported about the ambient context
|
|
|
|
|
if (isAccessor(node.parent.kind)) {
|
|
|
|
|
if (isAccessor(node.parent)) {
|
|
|
|
|
return getNodeLinks(node).hasReportedStatementInAmbientContext = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|