Merge pull request #29053 from Microsoft/fixDestructuringControlFlow

Fix destructuring control flow analysis
This commit is contained in:
Anders Hejlsberg
2018-12-19 11:12:41 -08:00
committed by GitHub
35 changed files with 759 additions and 303 deletions
+170 -187
View File
@@ -4783,6 +4783,69 @@ namespace ts {
return createAnonymousType(symbol, members, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo);
}
// Determine the control flow type associated with a destructuring declaration or assignment. The following
// forms of destructuring are possible:
// let { x } = obj; // BindingElement
// let [ x ] = obj; // BindingElement
// { x } = obj; // ShorthandPropertyAssignment
// { x: v } = obj; // PropertyAssignment
// [ x ] = obj; // Expression
// We construct a synthetic element access expression corresponding to 'obj.x' such that the control
// flow analyzer doesn't have to handle all the different syntactic forms.
function getFlowTypeOfDestructuring(node: BindingElement | PropertyAssignment | ShorthandPropertyAssignment | Expression, declaredType: Type) {
const reference = getSyntheticElementAccess(node);
return reference ? getFlowTypeOfReference(reference, declaredType) : declaredType;
}
function getSyntheticElementAccess(node: BindingElement | PropertyAssignment | ShorthandPropertyAssignment | Expression): ElementAccessExpression | undefined {
const parentAccess = getParentElementAccess(node);
if (parentAccess && parentAccess.flowNode) {
const propName = getDestructuringPropertyName(node);
if (propName) {
const result = <ElementAccessExpression>createNode(SyntaxKind.ElementAccessExpression, node.pos, node.end);
result.parent = node;
result.expression = <LeftHandSideExpression>parentAccess;
const literal = <StringLiteral>createNode(SyntaxKind.StringLiteral, node.pos, node.end);
literal.parent = result;
literal.text = propName;
result.argumentExpression = literal;
result.flowNode = parentAccess.flowNode;
return result;
}
}
}
function getParentElementAccess(node: BindingElement | PropertyAssignment | ShorthandPropertyAssignment | Expression) {
const ancestor = node.parent.parent;
switch (ancestor.kind) {
case SyntaxKind.BindingElement:
case SyntaxKind.PropertyAssignment:
return getSyntheticElementAccess(<BindingElement | PropertyAssignment>ancestor);
case SyntaxKind.ArrayLiteralExpression:
return getSyntheticElementAccess(<Expression>node.parent);
case SyntaxKind.VariableDeclaration:
return (<VariableDeclaration>ancestor).initializer;
case SyntaxKind.BinaryExpression:
return (<BinaryExpression>ancestor).right;
}
}
function getDestructuringPropertyName(node: BindingElement | PropertyAssignment | ShorthandPropertyAssignment | Expression) {
const parent = node.parent;
if (node.kind === SyntaxKind.BindingElement && parent.kind === SyntaxKind.ObjectBindingPattern) {
return getLiteralPropertyNameText((<BindingElement>node).propertyName || <Identifier>(<BindingElement>node).name);
}
if (node.kind === SyntaxKind.PropertyAssignment || node.kind === SyntaxKind.ShorthandPropertyAssignment) {
return getLiteralPropertyNameText((<PropertyAssignment | ShorthandPropertyAssignment>node).name);
}
return "" + (<NodeArray<Node>>(<BindingPattern | ArrayLiteralExpression>parent).elements).indexOf(node);
}
function getLiteralPropertyNameText(name: PropertyName) {
const type = getLiteralTypeFromPropertyName(name);
return type.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral) ? "" + (<LiteralType>type).value : undefined;
}
/** Return the inferred type for a binding element */
function getTypeForBindingElement(declaration: BindingElement): Type | undefined {
const pattern = declaration.parent;
@@ -4823,9 +4886,9 @@ namespace ts {
else {
// Use explicitly specified property name ({ p: xxx } form), or otherwise the implied name ({ p } form)
const name = declaration.propertyName || <Identifier>declaration.name;
const exprType = getLiteralTypeFromPropertyName(name);
const declaredType = checkIndexedAccessIndexType(getIndexedAccessType(parentType, exprType, name), name);
type = getFlowTypeOfReference(declaration, getConstraintForLocation(declaredType, declaration.name));
const indexType = getLiteralTypeFromPropertyName(name);
const declaredType = getConstraintForLocation(getIndexedAccessType(parentType, indexType, name), declaration.name);
type = getFlowTypeOfDestructuring(declaration, declaredType);
}
}
else {
@@ -4842,21 +4905,13 @@ namespace ts {
mapType(parentType, t => sliceTupleType(<TupleTypeReference>t, index)) :
createArrayType(elementType);
}
else if (isArrayLikeType(parentType)) {
const indexType = getLiteralType(index);
const declaredType = getConstraintForLocation(getIndexedAccessType(parentType, indexType, declaration.name), declaration.name);
type = getFlowTypeOfDestructuring(declaration, declaredType);
}
else {
// Use specific property type when parent is a tuple or numeric index type when parent is an array
const index = pattern.elements.indexOf(declaration);
type = everyType(parentType, isTupleLikeType) ?
getTupleElementType(parentType, index) || declaration.initializer && checkDeclarationInitializer(declaration) :
elementType;
if (!type) {
if (isTupleType(parentType)) {
error(declaration, Diagnostics.Tuple_type_0_with_length_1_cannot_be_assigned_to_tuple_with_length_2, typeToString(parentType), getTypeReferenceArity(<TypeReference>parentType), pattern.elements.length);
}
else {
error(declaration, Diagnostics.Type_0_has_no_property_1, typeToString(parentType), "" + index);
}
return errorType;
}
type = elementType;
}
}
// In strict null checking mode, if a default value of a non-undefined type is specified, remove
@@ -9538,16 +9593,16 @@ namespace ts {
return false;
}
function getPropertyTypeForIndexType(objectType: Type, indexType: Type, accessNode: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | undefined, cacheSymbol: boolean, missingType: Type) {
function getPropertyTypeForIndexType(objectType: Type, indexType: Type, accessNode: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression | undefined, cacheSymbol: boolean, missingType: Type) {
const accessExpression = accessNode && accessNode.kind === SyntaxKind.ElementAccessExpression ? accessNode : undefined;
const propName = isTypeUsableAsLateBoundName(indexType)
? getLateBoundNameFromType(indexType)
: accessExpression && checkThatExpressionIsProperSymbolReference(accessExpression.argumentExpression, indexType, /*reportError*/ false)
? getPropertyNameForKnownSymbolName(idText((<PropertyAccessExpression>accessExpression.argumentExpression).name))
: accessNode && isPropertyName(accessNode)
const propName = isTypeUsableAsLateBoundName(indexType) ?
getLateBoundNameFromType(indexType) :
accessExpression && checkThatExpressionIsProperSymbolReference(accessExpression.argumentExpression, indexType, /*reportError*/ false) ?
getPropertyNameForKnownSymbolName(idText((<PropertyAccessExpression>accessExpression.argumentExpression).name)) :
accessNode && isPropertyName(accessNode) ?
// late bound names are handled in the first branch, so here we only need to handle normal names
? getPropertyNameForPropertyNameNode(accessNode)
: undefined;
getPropertyNameForPropertyNameNode(accessNode) :
undefined;
if (propName !== undefined) {
const prop = getPropertyOfType(objectType, propName);
if (prop) {
@@ -9569,7 +9624,13 @@ namespace ts {
if (everyType(objectType, isTupleType) && isNumericLiteralName(propName) && +propName >= 0) {
if (accessNode && everyType(objectType, t => !(<TupleTypeReference>t).target.hasRestElement)) {
const indexNode = getIndexNodeForAccessExpression(accessNode);
error(indexNode, Diagnostics.Property_0_does_not_exist_on_type_1, unescapeLeadingUnderscores(propName), typeToString(objectType));
if (isTupleType(objectType)) {
error(indexNode, Diagnostics.Tuple_type_0_of_length_1_has_no_element_at_index_2,
typeToString(objectType), getTypeReferenceArity(objectType), unescapeLeadingUnderscores(propName));
}
else {
error(indexNode, Diagnostics.Property_0_does_not_exist_on_type_1, unescapeLeadingUnderscores(propName), typeToString(objectType));
}
}
return mapType(objectType, t => getRestTypeOfTupleType(<TupleTypeReference>t) || undefinedType);
}
@@ -9641,7 +9702,7 @@ namespace ts {
return missingType;
}
function getIndexNodeForAccessExpression(accessNode: ElementAccessExpression | IndexedAccessTypeNode | PropertyName) {
function getIndexNodeForAccessExpression(accessNode: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression) {
return accessNode.kind === SyntaxKind.ElementAccessExpression
? accessNode.argumentExpression
: accessNode.kind === SyntaxKind.IndexedAccessType
@@ -9710,7 +9771,7 @@ namespace ts {
return type.simplified = type;
}
function getIndexedAccessType(objectType: Type, indexType: Type, accessNode?: ElementAccessExpression | IndexedAccessTypeNode | PropertyName, missingType = accessNode ? errorType : unknownType): Type {
function getIndexedAccessType(objectType: Type, indexType: Type, accessNode?: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression, missingType = accessNode ? errorType : unknownType): Type {
if (objectType === wildcardType || indexType === wildcardType) {
return wildcardType;
}
@@ -14587,49 +14648,23 @@ namespace ts {
// occurring in an apparent type position with '@' because the control flow type
// of such nodes may be based on the apparent type instead of the declared type.
function getFlowCacheKey(node: Node): string | undefined {
if (node.kind === SyntaxKind.Identifier) {
const symbol = getResolvedSymbol(<Identifier>node);
return symbol !== unknownSymbol ? (isConstraintPosition(node) ? "@" : "") + getSymbolId(symbol) : undefined;
}
if (node.kind === SyntaxKind.ThisKeyword) {
return "0";
}
if (node.kind === SyntaxKind.PropertyAccessExpression) {
const key = getFlowCacheKey((<PropertyAccessExpression>node).expression);
return key && key + "." + idText((<PropertyAccessExpression>node).name);
}
if (node.kind === SyntaxKind.BindingElement) {
const container = (node as BindingElement).parent.parent;
const key = container.kind === SyntaxKind.BindingElement ? getFlowCacheKey(container) : (container.initializer && getFlowCacheKey(container.initializer));
const text = getBindingElementNameText(node as BindingElement);
const result = key && text && (key + "." + text);
return result;
switch (node.kind) {
case SyntaxKind.Identifier:
const symbol = getResolvedSymbol(<Identifier>node);
return symbol !== unknownSymbol ? (isConstraintPosition(node) ? "@" : "") + getSymbolId(symbol) : undefined;
case SyntaxKind.ThisKeyword:
return "0";
case SyntaxKind.PropertyAccessExpression:
case SyntaxKind.ElementAccessExpression:
const propName = getAccessedPropertyName(<AccessExpression>node);
if (propName !== undefined) {
const key = getFlowCacheKey((<AccessExpression>node).expression);
return key && key + "." + propName;
}
}
return undefined;
}
function getBindingElementNameText(element: BindingElement): string | undefined {
const parent = element.parent;
if (parent.kind === SyntaxKind.ObjectBindingPattern) {
const name = element.propertyName || element.name;
switch (name.kind) {
case SyntaxKind.Identifier:
return idText(name);
case SyntaxKind.ComputedPropertyName:
return isStringOrNumericLiteralLike(name.expression) ? name.expression.text : undefined;
case SyntaxKind.StringLiteral:
case SyntaxKind.NumericLiteral:
return name.text;
default:
// Per types, array and object binding patterns remain, however they should never be present if propertyName is not defined
Debug.fail("Unexpected name kind for binding element name");
}
}
else {
return "" + parent.elements.indexOf(element);
}
}
function isMatchingReference(source: Node, target: Node): boolean {
switch (source.kind) {
case SyntaxKind.Identifier:
@@ -14642,49 +14677,27 @@ namespace ts {
return target.kind === SyntaxKind.SuperKeyword;
case SyntaxKind.PropertyAccessExpression:
case SyntaxKind.ElementAccessExpression:
return (isPropertyAccessExpression(target) || isElementAccessExpression(target)) &&
getAccessedPropertyName(source as PropertyAccessExpression | ElementAccessExpression) === getAccessedPropertyName(target) &&
isMatchingReference((source as PropertyAccessExpression | ElementAccessExpression).expression, target.expression);
case SyntaxKind.BindingElement:
if (target.kind === SyntaxKind.PropertyAccessExpression && (<PropertyAccessExpression>target).name.escapedText === getBindingElementNameText(<BindingElement>source)) {
const ancestor = source.parent.parent;
if (ancestor.kind === SyntaxKind.BindingElement) {
return isMatchingReference(ancestor, (<PropertyAccessExpression>target).expression);
}
if (ancestor.kind === SyntaxKind.VariableDeclaration) {
const initializer = (<VariableDeclaration>ancestor).initializer;
return !!initializer && isMatchingReference(initializer, (<PropertyAccessExpression>target).expression);
}
}
return isAccessExpression(target) &&
getAccessedPropertyName(<AccessExpression>source) === getAccessedPropertyName(target) &&
isMatchingReference((<AccessExpression>source).expression, target.expression);
}
return false;
}
function getAccessedPropertyName(access: PropertyAccessExpression | ElementAccessExpression): __String | undefined {
return isPropertyAccessExpression(access) ? access.name.escapedText :
function getAccessedPropertyName(access: AccessExpression): __String | undefined {
return access.kind === SyntaxKind.PropertyAccessExpression ? access.name.escapedText :
isStringLiteral(access.argumentExpression) || isNumericLiteral(access.argumentExpression) ? escapeLeadingUnderscores(access.argumentExpression.text) :
undefined;
}
function getReferenceParent(source: Node) {
if (source.kind === SyntaxKind.PropertyAccessExpression) {
return (<PropertyAccessExpression>source).expression;
}
if (source.kind === SyntaxKind.BindingElement) {
const ancestor = source.parent.parent;
return ancestor.kind === SyntaxKind.VariableDeclaration ? (<VariableDeclaration>ancestor).initializer : ancestor;
}
return undefined;
}
function containsMatchingReference(source: Node, target: Node) {
let parent = getReferenceParent(source);
while (parent) {
if (isMatchingReference(parent, target)) {
while (isAccessExpression(source)) {
source = source.expression;
if (isMatchingReference(source, target)) {
return true;
}
parent = getReferenceParent(parent);
}
return false;
}
// Return true if target is a property access xxx.yyy, source is a property access xxx.zzz, the declared
@@ -14692,18 +14705,23 @@ namespace ts {
// a possible discriminant if its type differs in the constituents of containing union type, and if every
// choice is a unit type or a union of unit types.
function containsMatchingReferenceDiscriminant(source: Node, target: Node) {
return target.kind === SyntaxKind.PropertyAccessExpression &&
containsMatchingReference(source, (<PropertyAccessExpression>target).expression) &&
isDiscriminantProperty(getDeclaredTypeOfReference((<PropertyAccessExpression>target).expression), (<PropertyAccessExpression>target).name.escapedText);
let name;
return isAccessExpression(target) &&
containsMatchingReference(source, target.expression) &&
(name = getAccessedPropertyName(target)) !== undefined &&
isDiscriminantProperty(getDeclaredTypeOfReference(target.expression), name);
}
function getDeclaredTypeOfReference(expr: Node): Type | undefined {
if (expr.kind === SyntaxKind.Identifier) {
return getTypeOfSymbol(getResolvedSymbol(<Identifier>expr));
}
if (expr.kind === SyntaxKind.PropertyAccessExpression) {
const type = getDeclaredTypeOfReference((<PropertyAccessExpression>expr).expression);
return type && getTypeOfPropertyOfType(type, (<PropertyAccessExpression>expr).name.escapedText);
if (isAccessExpression(expr)) {
const type = getDeclaredTypeOfReference(expr.expression);
if (type) {
const propName = getAccessedPropertyName(expr);
return propName !== undefined ? getTypeOfPropertyOfType(type, propName) : undefined;
}
}
return undefined;
}
@@ -15529,7 +15547,7 @@ namespace ts {
else if (isMatchingReferenceDiscriminant(expr, type)) {
type = narrowTypeByDiscriminant(
type,
expr as PropertyAccessExpression | ElementAccessExpression,
expr as AccessExpression,
t => narrowTypeBySwitchOnDiscriminant(t, flow.switchStatement, flow.clauseStart, flow.clauseEnd));
}
else if (expr.kind === SyntaxKind.TypeOfExpression && isMatchingReference(reference, (expr as TypeOfExpression).expression)) {
@@ -15649,21 +15667,19 @@ namespace ts {
}
function isMatchingReferenceDiscriminant(expr: Expression, computedType: Type) {
if (!(computedType.flags & TypeFlags.Union) ||
expr.kind !== SyntaxKind.PropertyAccessExpression && expr.kind !== SyntaxKind.ElementAccessExpression) {
if (!(computedType.flags & TypeFlags.Union) || !isAccessExpression(expr)) {
return false;
}
const access = expr as PropertyAccessExpression | ElementAccessExpression;
const name = getAccessedPropertyName(access);
if (!name) {
const name = getAccessedPropertyName(expr);
if (name === undefined) {
return false;
}
return isMatchingReference(reference, access.expression) && isDiscriminantProperty(computedType, name);
return isMatchingReference(reference, expr.expression) && isDiscriminantProperty(computedType, name);
}
function narrowTypeByDiscriminant(type: Type, access: PropertyAccessExpression | ElementAccessExpression, narrowType: (t: Type) => Type): Type {
function narrowTypeByDiscriminant(type: Type, access: AccessExpression, narrowType: (t: Type) => Type): Type {
const propName = getAccessedPropertyName(access);
if (!propName) {
if (propName === undefined) {
return type;
}
const propType = getTypeOfPropertyOfType(type, propName);
@@ -15676,7 +15692,7 @@ namespace ts {
return getTypeWithFacts(type, assumeTrue ? TypeFacts.Truthy : TypeFacts.Falsy);
}
if (isMatchingReferenceDiscriminant(expr, declaredType)) {
return narrowTypeByDiscriminant(type, <PropertyAccessExpression | ElementAccessExpression>expr, t => getTypeWithFacts(t, assumeTrue ? TypeFacts.Truthy : TypeFacts.Falsy));
return narrowTypeByDiscriminant(type, <AccessExpression>expr, t => getTypeWithFacts(t, assumeTrue ? TypeFacts.Truthy : TypeFacts.Falsy));
}
if (containsMatchingReferenceDiscriminant(reference, expr)) {
return declaredType;
@@ -15727,10 +15743,10 @@ namespace ts {
return narrowTypeByEquality(type, operator, left, assumeTrue);
}
if (isMatchingReferenceDiscriminant(left, declaredType)) {
return narrowTypeByDiscriminant(type, <PropertyAccessExpression | ElementAccessExpression>left, t => narrowTypeByEquality(t, operator, right, assumeTrue));
return narrowTypeByDiscriminant(type, <AccessExpression>left, t => narrowTypeByEquality(t, operator, right, assumeTrue));
}
if (isMatchingReferenceDiscriminant(right, declaredType)) {
return narrowTypeByDiscriminant(type, <PropertyAccessExpression | ElementAccessExpression>right, t => narrowTypeByEquality(t, operator, left, assumeTrue));
return narrowTypeByDiscriminant(type, <AccessExpression>right, t => narrowTypeByEquality(t, operator, left, assumeTrue));
}
if (containsMatchingReferenceDiscriminant(reference, left) || containsMatchingReferenceDiscriminant(reference, right)) {
return declaredType;
@@ -16035,9 +16051,8 @@ namespace ts {
}
else {
const invokedExpression = skipParentheses(callExpression.expression);
if (invokedExpression.kind === SyntaxKind.ElementAccessExpression || invokedExpression.kind === SyntaxKind.PropertyAccessExpression) {
const accessExpression = invokedExpression as ElementAccessExpression | PropertyAccessExpression;
const possibleReference = skipParentheses(accessExpression.expression);
if (isAccessExpression(invokedExpression)) {
const possibleReference = skipParentheses(invokedExpression.expression);
if (isMatchingReference(reference, possibleReference)) {
return getNarrowedType(type, predicate.type, assumeTrue, isTypeSubtypeOf);
}
@@ -16980,7 +16995,7 @@ namespace ts {
if (parent.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>parent).operatorToken.kind === SyntaxKind.EqualsToken) {
const target = (<BinaryExpression>parent).left;
if (target.kind === SyntaxKind.PropertyAccessExpression || target.kind === SyntaxKind.ElementAccessExpression) {
const { expression } = target as PropertyAccessExpression | ElementAccessExpression;
const { expression } = target as AccessExpression;
// Don't contextually type `this` as `exports` in `exports.Point = function(x, y) { this.x = x; this.y = y; }`
if (inJs && isIdentifier(expression)) {
const sourceFile = getSourceFileOfNode(parent);
@@ -19736,7 +19751,7 @@ namespace ts {
if (node.kind === SyntaxKind.CallExpression) {
const callee = skipOuterExpressions(node.expression);
if (callee.kind === SyntaxKind.PropertyAccessExpression || callee.kind === SyntaxKind.ElementAccessExpression) {
return (callee as PropertyAccessExpression | ElementAccessExpression).expression;
return (callee as AccessExpression).expression;
}
}
}
@@ -21768,7 +21783,7 @@ namespace ts {
// Allow assignments to readonly properties within constructors of the same class declaration.
if (symbol.flags & SymbolFlags.Property &&
(expr.kind === SyntaxKind.PropertyAccessExpression || expr.kind === SyntaxKind.ElementAccessExpression) &&
(expr as PropertyAccessExpression | ElementAccessExpression).expression.kind === SyntaxKind.ThisKeyword) {
(expr as AccessExpression).expression.kind === SyntaxKind.ThisKeyword) {
// Look for if this is the constructor for the class that `symbol` is a property of.
const func = getContainingFunction(expr);
if (!(func && func.kind === SyntaxKind.Constructor)) {
@@ -21786,7 +21801,7 @@ namespace ts {
function isReferenceThroughNamespaceImport(expr: Expression): boolean {
if (expr.kind === SyntaxKind.PropertyAccessExpression || expr.kind === SyntaxKind.ElementAccessExpression) {
const node = skipParentheses((expr as PropertyAccessExpression | ElementAccessExpression).expression);
const node = skipParentheses((expr as AccessExpression).expression);
if (node.kind === SyntaxKind.Identifier) {
const symbol = getNodeLinks(node).resolvedSymbol!;
if (symbol.flags & SymbolFlags.Alias) {
@@ -22035,21 +22050,18 @@ namespace ts {
function checkObjectLiteralDestructuringPropertyAssignment(objectLiteralType: Type, property: ObjectLiteralElementLike, allProperties?: NodeArray<ObjectLiteralElementLike>, rightIsThis = false) {
if (property.kind === SyntaxKind.PropertyAssignment || property.kind === SyntaxKind.ShorthandPropertyAssignment) {
const name = property.name;
if (name.kind === SyntaxKind.ComputedPropertyName) {
checkComputedPropertyName(name);
}
if (isComputedNonLiteralName(name)) {
return undefined;
}
const type = getTypeOfObjectLiteralDestructuringProperty(objectLiteralType, name, property, rightIsThis);
if (type) {
// non-shorthand property assignments should always have initializers
return checkDestructuringAssignment(property.kind === SyntaxKind.ShorthandPropertyAssignment ? property : property.initializer, type);
}
else {
error(name, Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(objectLiteralType), declarationNameToString(name));
const text = getTextOfPropertyName(name);
if (text) {
const prop = getPropertyOfType(objectLiteralType, text);
if (prop) {
markPropertyAsReferenced(prop, property, rightIsThis);
checkPropertyAccessibility(property, /*isSuper*/ false, objectLiteralType, prop);
}
}
const exprType = getLiteralTypeFromPropertyName(name);
const elementType = getIndexedAccessType(objectLiteralType, exprType, name);
const type = getFlowTypeOfDestructuring(property, elementType);
return checkDestructuringAssignment(property.kind === SyntaxKind.ShorthandPropertyAssignment ? property : property.initializer, type);
}
else if (property.kind === SyntaxKind.SpreadAssignment) {
if (languageVersion < ScriptTarget.ESNext) {
@@ -22070,31 +22082,11 @@ namespace ts {
}
}
function getTypeOfObjectLiteralDestructuringProperty(objectLiteralType: Type, name: PropertyName, property: PropertyAssignment | ShorthandPropertyAssignment, rightIsThis: boolean) {
if (isTypeAny(objectLiteralType)) {
return objectLiteralType;
}
let type: Type | undefined;
const text = getTextOfPropertyName(name);
if (text) { // TODO: GH#26379
const prop = getPropertyOfType(objectLiteralType, text);
if (prop) {
markPropertyAsReferenced(prop, property, rightIsThis);
checkPropertyAccessibility(property, /*isSuper*/ false, objectLiteralType, prop);
type = getTypeOfSymbol(prop);
}
type = type || (isNumericLiteralName(text) ? getIndexTypeOfType(objectLiteralType, IndexKind.Number) : undefined);
}
return type || getIndexTypeOfType(objectLiteralType, IndexKind.String);
}
function checkArrayLiteralAssignment(node: ArrayLiteralExpression, sourceType: Type, checkMode?: CheckMode): Type {
const elements = node.elements;
if (languageVersion < ScriptTarget.ES2015 && compilerOptions.downlevelIteration) {
checkExternalEmitHelpers(node, ExternalEmitHelpers.Read);
}
// 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).
@@ -22111,39 +22103,30 @@ namespace ts {
const element = elements[elementIndex];
if (element.kind !== SyntaxKind.OmittedExpression) {
if (element.kind !== SyntaxKind.SpreadElement) {
const propName = "" + elementIndex as __String;
const type = isTypeAny(sourceType) ? sourceType :
everyType(sourceType, isTupleLikeType) ? getTupleElementType(sourceType, elementIndex) :
elementType;
if (type) {
const indexType = getLiteralType(elementIndex);
if (isArrayLikeType(sourceType)) {
// We create a synthetic expression so that getIndexedAccessType doesn't get confused
// when the element is a SyntaxKind.ElementAccessExpression.
const elementType = getIndexedAccessType(sourceType, indexType, createSyntheticExpression(element, indexType));
const type = getFlowTypeOfDestructuring(element, elementType);
return checkDestructuringAssignment(element, type, checkMode);
}
// We still need to check element expression here because we may need to set appropriate flag on the expression
// such as NodeCheckFlags.LexicalThis on "this"expression.
checkExpression(element);
if (isTupleType(sourceType)) {
error(element, Diagnostics.Tuple_type_0_with_length_1_cannot_be_assigned_to_tuple_with_length_2, typeToString(sourceType), getTypeReferenceArity(<TypeReference>sourceType), elements.length);
}
else {
error(element, Diagnostics.Type_0_has_no_property_1, typeToString(sourceType), propName as string);
}
return checkDestructuringAssignment(element, elementType, checkMode);
}
if (elementIndex < elements.length - 1) {
error(element, Diagnostics.A_rest_element_must_be_last_in_a_destructuring_pattern);
}
else {
if (elementIndex < elements.length - 1) {
error(element, Diagnostics.A_rest_element_must_be_last_in_a_destructuring_pattern);
const restExpression = (<SpreadElement>element).expression;
if (restExpression.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>restExpression).operatorToken.kind === SyntaxKind.EqualsToken) {
error((<BinaryExpression>restExpression).operatorToken, Diagnostics.A_rest_element_cannot_have_an_initializer);
}
else {
const restExpression = (<SpreadElement>element).expression;
if (restExpression.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>restExpression).operatorToken.kind === SyntaxKind.EqualsToken) {
error((<BinaryExpression>restExpression).operatorToken, Diagnostics.A_rest_element_cannot_have_an_initializer);
}
else {
checkGrammarForDisallowedTrailingComma(node.elements, Diagnostics.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma);
const type = everyType(sourceType, isTupleType) ?
mapType(sourceType, t => sliceTupleType(<TupleTypeReference>t, elementIndex)) :
createArrayType(elementType);
return checkDestructuringAssignment(restExpression, type, checkMode);
}
checkGrammarForDisallowedTrailingComma(node.elements, Diagnostics.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma);
const type = everyType(sourceType, isTupleType) ?
mapType(sourceType, t => sliceTupleType(<TupleTypeReference>t, elementIndex)) :
createArrayType(elementType);
return checkDestructuringAssignment(restExpression, type, checkMode);
}
}
}
@@ -26982,7 +26965,7 @@ namespace ts {
return nodeIsMissing(expr) ? 0 : evaluateEnumMember(expr, getSymbolOfNode(member.parent), identifier.escapedText);
case SyntaxKind.ElementAccessExpression:
case SyntaxKind.PropertyAccessExpression:
const ex = <PropertyAccessExpression | ElementAccessExpression>expr;
const ex = <AccessExpression>expr;
if (isConstantMemberAccess(ex)) {
const type = getTypeOfExpression(ex.expression);
if (type.symbol && type.symbol.flags & SymbolFlags.Enum) {
@@ -28956,7 +28939,7 @@ namespace ts {
return getNodeLinks(node).enumMemberValue;
}
function canHaveConstantValue(node: Node): node is EnumMember | PropertyAccessExpression | ElementAccessExpression {
function canHaveConstantValue(node: Node): node is EnumMember | AccessExpression {
switch (node.kind) {
case SyntaxKind.EnumMember:
case SyntaxKind.PropertyAccessExpression:
@@ -28966,7 +28949,7 @@ namespace ts {
return false;
}
function getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): string | number | undefined {
function getConstantValue(node: EnumMember | AccessExpression): string | number | undefined {
if (node.kind === SyntaxKind.EnumMember) {
return getEnumMemberValue(node);
}
+1 -9
View File
@@ -1644,14 +1644,6 @@
"category": "Error",
"code": 2458
},
"Type '{0}' has no property '{1}' and no string index signature.": {
"category": "Error",
"code": 2459
},
"Type '{0}' has no property '{1}'.": {
"category": "Error",
"code": 2460
},
"Type '{0}' is not an array type.": {
"category": "Error",
"code": 2461
@@ -1768,7 +1760,7 @@
"category": "Error",
"code": 2492
},
"Tuple type '{0}' with length '{1}' cannot be assigned to tuple with length '{2}'.": {
"Tuple type '{0}' of length '{1}' has no element at index '{2}'.": {
"category": "Error",
"code": 2493
},
+3
View File
@@ -1745,6 +1745,9 @@ namespace ts {
export type EntityNameExpression = Identifier | PropertyAccessEntityNameExpression;
export type EntityNameOrEntityNameExpression = EntityName | EntityNameExpression;
/* @internal */
export type AccessExpression = PropertyAccessExpression | ElementAccessExpression;
export interface PropertyAccessExpression extends MemberExpression, NamedDeclaration {
kind: SyntaxKind.PropertyAccessExpression;
expression: LeftHandSideExpression;
+4
View File
@@ -4590,6 +4590,10 @@ namespace ts {
|| kind === SyntaxKind.JSDocFunctionType
|| kind === SyntaxKind.JSDocVariadicType;
}
export function isAccessExpression(node: Node): node is AccessExpression {
return node.kind === SyntaxKind.PropertyAccessExpression || node.kind === SyntaxKind.ElementAccessExpression;
}
}
namespace ts {
@@ -1,5 +1,5 @@
tests/cases/conformance/statements/for-ofStatements/ES5For-of31.ts(3,8): error TS2459: Type 'undefined' has no property 'a' and no string index signature.
tests/cases/conformance/statements/for-ofStatements/ES5For-of31.ts(3,18): error TS2459: Type 'undefined' has no property 'b' and no string index signature.
tests/cases/conformance/statements/for-ofStatements/ES5For-of31.ts(3,8): error TS2339: Property 'a' does not exist on type 'undefined'.
tests/cases/conformance/statements/for-ofStatements/ES5For-of31.ts(3,18): error TS2339: Property 'b' does not exist on type 'undefined'.
==== tests/cases/conformance/statements/for-ofStatements/ES5For-of31.ts (2 errors) ====
@@ -7,9 +7,9 @@ tests/cases/conformance/statements/for-ofStatements/ES5For-of31.ts(3,18): error
for ({ a: b = 1, b: a = ""} of []) {
~
!!! error TS2459: Type 'undefined' has no property 'a' and no string index signature.
!!! error TS2339: Property 'a' does not exist on type 'undefined'.
~
!!! error TS2459: Type 'undefined' has no property 'b' and no string index signature.
!!! error TS2339: Property 'b' does not exist on type 'undefined'.
a;
b;
}
@@ -1,7 +1,5 @@
tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(15,12): error TS2493: Tuple type '[string, number]' with length '2' cannot be assigned to tuple with length '3'.
tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(16,12): error TS2460: Type 'StrNum' has no property '2'.
tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(15,12): error TS2493: Tuple type '[string, number]' of length '2' has no element at index '2'.
tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(17,5): error TS2461: Type '{ 0: string; 1: number; length: 2; }' is not an array type.
tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(17,12): error TS2460: Type '{ 0: string; 1: number; length: 2; }' has no property '2'.
tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(18,5): error TS2741: Property '2' is missing in type '[string, number]' but required in type '[number, number, number]'.
tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(19,5): error TS2741: Property '2' is missing in type 'StrNum' but required in type '[number, number, number]'.
tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(20,5): error TS2740: Type '{ 0: string; 1: number; length: 2; }' is missing the following properties from type '[number, number, number]': 2, pop, push, concat, and 16 more.
@@ -30,7 +28,7 @@ tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(31,5): error
tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(32,5): error TS2740: Type '{ 0: string; 1: number; length: 2; }' is missing the following properties from type '[number, string]': pop, push, concat, join, and 15 more.
==== tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts (19 errors) ====
==== tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts (17 errors) ====
interface StrNum extends Array<string|number> {
0: string;
1: number;
@@ -47,15 +45,11 @@ tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(32,5): error
var [a, b, c] = x;
~
!!! error TS2493: Tuple type '[string, number]' with length '2' cannot be assigned to tuple with length '3'.
!!! error TS2493: Tuple type '[string, number]' of length '2' has no element at index '2'.
var [d, e, f] = y;
~
!!! error TS2460: Type 'StrNum' has no property '2'.
var [g, h, i] = z;
~~~~~~~~~
!!! error TS2461: Type '{ 0: string; 1: number; length: 2; }' is not an array type.
~
!!! error TS2460: Type '{ 0: string; 1: number; length: 2; }' has no property '2'.
var j1: [number, number, number] = x;
~~
!!! error TS2741: Property '2' is missing in type '[string, number]' but required in type '[number, number, number]'.
@@ -32,18 +32,18 @@ var z: {
var [a, b, c] = x;
>a : string
>b : number
>c : any
>c : undefined
>x : [string, number]
var [d, e, f] = y;
>d : string
>e : number
>f : any
>f : string | number
>y : StrNum
var [g, h, i] = z;
>g : string
>h : number
>g : any
>h : any
>i : any
>z : { 0: string; 1: number; length: 2; }
@@ -1,7 +1,7 @@
tests/cases/conformance/types/typeRelationships/bestCommonType/bestCommonTypeOfTuple.ts(22,13): error TS2339: Property '2' does not exist on type '[(x: number) => string, (x: number) => number]'.
tests/cases/conformance/types/typeRelationships/bestCommonType/bestCommonTypeOfTuple.ts(23,13): error TS2339: Property '2' does not exist on type '[E1, E2]'.
tests/cases/conformance/types/typeRelationships/bestCommonType/bestCommonTypeOfTuple.ts(24,13): error TS2339: Property '2' does not exist on type '[number, any]'.
tests/cases/conformance/types/typeRelationships/bestCommonType/bestCommonTypeOfTuple.ts(25,13): error TS2339: Property '3' does not exist on type '[E1, E2, number]'.
tests/cases/conformance/types/typeRelationships/bestCommonType/bestCommonTypeOfTuple.ts(22,13): error TS2493: Tuple type '[(x: number) => string, (x: number) => number]' of length '2' has no element at index '2'.
tests/cases/conformance/types/typeRelationships/bestCommonType/bestCommonTypeOfTuple.ts(23,13): error TS2493: Tuple type '[E1, E2]' of length '2' has no element at index '2'.
tests/cases/conformance/types/typeRelationships/bestCommonType/bestCommonTypeOfTuple.ts(24,13): error TS2493: Tuple type '[number, any]' of length '2' has no element at index '2'.
tests/cases/conformance/types/typeRelationships/bestCommonType/bestCommonTypeOfTuple.ts(25,13): error TS2493: Tuple type '[E1, E2, number]' of length '3' has no element at index '3'.
==== tests/cases/conformance/types/typeRelationships/bestCommonType/bestCommonTypeOfTuple.ts (4 errors) ====
@@ -28,13 +28,13 @@ tests/cases/conformance/types/typeRelationships/bestCommonType/bestCommonTypeOfT
t4 = [E1.one, E2.two, 20];
var e1 = t1[2]; // {}
~
!!! error TS2339: Property '2' does not exist on type '[(x: number) => string, (x: number) => number]'.
!!! error TS2493: Tuple type '[(x: number) => string, (x: number) => number]' of length '2' has no element at index '2'.
var e2 = t2[2]; // {}
~
!!! error TS2339: Property '2' does not exist on type '[E1, E2]'.
!!! error TS2493: Tuple type '[E1, E2]' of length '2' has no element at index '2'.
var e3 = t3[2]; // any
~
!!! error TS2339: Property '2' does not exist on type '[number, any]'.
!!! error TS2493: Tuple type '[number, any]' of length '2' has no element at index '2'.
var e4 = t4[3]; // number
~
!!! error TS2339: Property '3' does not exist on type '[E1, E2, number]'.
!!! error TS2493: Tuple type '[E1, E2, number]' of length '3' has no element at index '3'.
@@ -1,8 +1,8 @@
tests/cases/conformance/types/typeRelationships/bestCommonType/bestCommonTypeOfTuple2.ts(17,14): error TS2339: Property '4' does not exist on type '[C, base]'.
tests/cases/conformance/types/typeRelationships/bestCommonType/bestCommonTypeOfTuple2.ts(18,14): error TS2339: Property '4' does not exist on type '[C, D]'.
tests/cases/conformance/types/typeRelationships/bestCommonType/bestCommonTypeOfTuple2.ts(19,14): error TS2339: Property '4' does not exist on type '[C1, D1]'.
tests/cases/conformance/types/typeRelationships/bestCommonType/bestCommonTypeOfTuple2.ts(20,14): error TS2339: Property '2' does not exist on type '[base1, C1]'.
tests/cases/conformance/types/typeRelationships/bestCommonType/bestCommonTypeOfTuple2.ts(21,14): error TS2339: Property '2' does not exist on type '[C1, F]'.
tests/cases/conformance/types/typeRelationships/bestCommonType/bestCommonTypeOfTuple2.ts(17,14): error TS2493: Tuple type '[C, base]' of length '2' has no element at index '4'.
tests/cases/conformance/types/typeRelationships/bestCommonType/bestCommonTypeOfTuple2.ts(18,14): error TS2493: Tuple type '[C, D]' of length '2' has no element at index '4'.
tests/cases/conformance/types/typeRelationships/bestCommonType/bestCommonTypeOfTuple2.ts(19,14): error TS2493: Tuple type '[C1, D1]' of length '2' has no element at index '4'.
tests/cases/conformance/types/typeRelationships/bestCommonType/bestCommonTypeOfTuple2.ts(20,14): error TS2493: Tuple type '[base1, C1]' of length '2' has no element at index '2'.
tests/cases/conformance/types/typeRelationships/bestCommonType/bestCommonTypeOfTuple2.ts(21,14): error TS2493: Tuple type '[C1, F]' of length '2' has no element at index '2'.
==== tests/cases/conformance/types/typeRelationships/bestCommonType/bestCommonTypeOfTuple2.ts (5 errors) ====
@@ -24,17 +24,17 @@ tests/cases/conformance/types/typeRelationships/bestCommonType/bestCommonTypeOfT
var e11 = t1[4]; // base
~
!!! error TS2339: Property '4' does not exist on type '[C, base]'.
!!! error TS2493: Tuple type '[C, base]' of length '2' has no element at index '4'.
var e21 = t2[4]; // {}
~
!!! error TS2339: Property '4' does not exist on type '[C, D]'.
!!! error TS2493: Tuple type '[C, D]' of length '2' has no element at index '4'.
var e31 = t3[4]; // C1
~
!!! error TS2339: Property '4' does not exist on type '[C1, D1]'.
!!! error TS2493: Tuple type '[C1, D1]' of length '2' has no element at index '4'.
var e41 = t4[2]; // base1
~
!!! error TS2339: Property '2' does not exist on type '[base1, C1]'.
!!! error TS2493: Tuple type '[base1, C1]' of length '2' has no element at index '2'.
var e51 = t5[2]; // {}
~
!!! error TS2339: Property '2' does not exist on type '[C1, F]'.
!!! error TS2493: Tuple type '[C1, F]' of length '2' has no element at index '2'.
@@ -6,7 +6,7 @@ tests/cases/conformance/types/tuple/castingTuple.ts(14,15): error TS2352: Conver
tests/cases/conformance/types/tuple/castingTuple.ts(15,14): error TS2352: Conversion of type '[number, string]' to type '[number, string, boolean]' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
tests/cases/conformance/types/tuple/castingTuple.ts(18,21): error TS2352: Conversion of type '[C, D]' to type '[C, D, A]' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
Property '2' is missing in type '[C, D]' but required in type '[C, D, A]'.
tests/cases/conformance/types/tuple/castingTuple.ts(20,33): error TS2339: Property '5' does not exist on type '[C, D, A]'.
tests/cases/conformance/types/tuple/castingTuple.ts(20,33): error TS2493: Tuple type '[C, D, A]' of length '3' has no element at index '5'.
tests/cases/conformance/types/tuple/castingTuple.ts(30,10): error TS2352: Conversion of type '[number, string]' to type '[number, number]' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
Type 'string' is not comparable to type 'number'.
tests/cases/conformance/types/tuple/castingTuple.ts(31,10): error TS2352: Conversion of type '[C, D]' to type '[A, I]' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
@@ -49,7 +49,7 @@ tests/cases/conformance/types/tuple/castingTuple.ts(33,1): error TS2304: Cannot
var eleFromCDA1 = classCDATuple[2]; // A
var eleFromCDA2 = classCDATuple[5]; // C | D | A
~
!!! error TS2339: Property '5' does not exist on type '[C, D, A]'.
!!! error TS2493: Tuple type '[C, D, A]' of length '3' has no element at index '5'.
var t10: [E1, E2] = [E1.one, E2.one];
var t11 = <[number, number]>t10;
var array1 = <{}[]>emptyObjTuple;
@@ -10,11 +10,17 @@ tests/cases/compiler/computedPropertiesInDestructuring1.ts(20,8): error TS2349:
tests/cases/compiler/computedPropertiesInDestructuring1.ts(20,8): error TS2538: Type 'any' cannot be used as an index type.
tests/cases/compiler/computedPropertiesInDestructuring1.ts(21,8): error TS2538: Type 'any' cannot be used as an index type.
tests/cases/compiler/computedPropertiesInDestructuring1.ts(21,12): error TS2339: Property 'toExponential' does not exist on type 'string'.
tests/cases/compiler/computedPropertiesInDestructuring1.ts(24,4): error TS2537: Type '{ bar: string; }' has no matching index signature for type 'string'.
tests/cases/compiler/computedPropertiesInDestructuring1.ts(28,4): error TS2537: Type '{ bar: string; }' has no matching index signature for type 'string'.
tests/cases/compiler/computedPropertiesInDestructuring1.ts(30,4): error TS2537: Type '{ bar: string; }' has no matching index signature for type 'string'.
tests/cases/compiler/computedPropertiesInDestructuring1.ts(31,4): error TS2537: Type '{ bar: string; }' has no matching index signature for type 'string'.
tests/cases/compiler/computedPropertiesInDestructuring1.ts(33,4): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures.
tests/cases/compiler/computedPropertiesInDestructuring1.ts(33,4): error TS2538: Type 'any' cannot be used as an index type.
tests/cases/compiler/computedPropertiesInDestructuring1.ts(34,4): error TS2538: Type 'any' cannot be used as an index type.
tests/cases/compiler/computedPropertiesInDestructuring1.ts(34,5): error TS2365: Operator '+' cannot be applied to types '1' and '{}'.
==== tests/cases/compiler/computedPropertiesInDestructuring1.ts (14 errors) ====
==== tests/cases/compiler/computedPropertiesInDestructuring1.ts (20 errors) ====
// destructuring in variable declarations
let foo = "bar";
let {[foo]: bar} = {bar: "bar"};
@@ -63,18 +69,30 @@ tests/cases/compiler/computedPropertiesInDestructuring1.ts(34,5): error TS2365:
// destructuring assignment
({[foo]: bar} = {bar: "bar"});
~~~
!!! error TS2537: Type '{ bar: string; }' has no matching index signature for type 'string'.
({["bar"]: bar2} = {bar: "bar"});
({[foo2()]: bar3} = {bar: "bar"});
~~~~~~
!!! error TS2537: Type '{ bar: string; }' has no matching index signature for type 'string'.
[{[foo]: bar4}] = [{bar: "bar"}];
~~~
!!! error TS2537: Type '{ bar: string; }' has no matching index signature for type 'string'.
[{[foo2()]: bar5}] = [{bar: "bar"}];
~~~~~~
!!! error TS2537: Type '{ bar: string; }' has no matching index signature for type 'string'.
[{[foo()]: bar4}] = [{bar: "bar"}];
~~~~~
!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures.
~~~~~
!!! error TS2538: Type 'any' cannot be used as an index type.
[{[(1 + {})]: bar4}] = [{bar: "bar"}];
~~~~~~~~
!!! error TS2538: Type 'any' cannot be used as an index type.
~~~~~~
!!! error TS2365: Operator '+' cannot be applied to types '1' and '{}'.
@@ -10,11 +10,17 @@ tests/cases/compiler/computedPropertiesInDestructuring1_ES6.ts(21,8): error TS23
tests/cases/compiler/computedPropertiesInDestructuring1_ES6.ts(21,8): error TS2538: Type 'any' cannot be used as an index type.
tests/cases/compiler/computedPropertiesInDestructuring1_ES6.ts(22,8): error TS2538: Type 'any' cannot be used as an index type.
tests/cases/compiler/computedPropertiesInDestructuring1_ES6.ts(22,12): error TS2339: Property 'toExponential' does not exist on type 'string'.
tests/cases/compiler/computedPropertiesInDestructuring1_ES6.ts(25,4): error TS2537: Type '{ bar: string; }' has no matching index signature for type 'string'.
tests/cases/compiler/computedPropertiesInDestructuring1_ES6.ts(29,4): error TS2537: Type '{ bar: string; }' has no matching index signature for type 'string'.
tests/cases/compiler/computedPropertiesInDestructuring1_ES6.ts(31,4): error TS2537: Type '{ bar: string; }' has no matching index signature for type 'string'.
tests/cases/compiler/computedPropertiesInDestructuring1_ES6.ts(32,4): error TS2537: Type '{ bar: string; }' has no matching index signature for type 'string'.
tests/cases/compiler/computedPropertiesInDestructuring1_ES6.ts(34,4): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures.
tests/cases/compiler/computedPropertiesInDestructuring1_ES6.ts(34,4): error TS2538: Type 'any' cannot be used as an index type.
tests/cases/compiler/computedPropertiesInDestructuring1_ES6.ts(35,4): error TS2538: Type 'any' cannot be used as an index type.
tests/cases/compiler/computedPropertiesInDestructuring1_ES6.ts(35,5): error TS2365: Operator '+' cannot be applied to types '1' and '{}'.
==== tests/cases/compiler/computedPropertiesInDestructuring1_ES6.ts (14 errors) ====
==== tests/cases/compiler/computedPropertiesInDestructuring1_ES6.ts (20 errors) ====
// destructuring in variable declarations
let foo = "bar";
let {[foo]: bar} = {bar: "bar"};
@@ -64,18 +70,30 @@ tests/cases/compiler/computedPropertiesInDestructuring1_ES6.ts(35,5): error TS23
// destructuring assignment
({[foo]: bar} = {bar: "bar"});
~~~
!!! error TS2537: Type '{ bar: string; }' has no matching index signature for type 'string'.
({["bar"]: bar2} = {bar: "bar"});
({[foo2()]: bar3} = {bar: "bar"});
~~~~~~
!!! error TS2537: Type '{ bar: string; }' has no matching index signature for type 'string'.
[{[foo]: bar4}] = [{bar: "bar"}];
~~~
!!! error TS2537: Type '{ bar: string; }' has no matching index signature for type 'string'.
[{[foo2()]: bar5}] = [{bar: "bar"}];
~~~~~~
!!! error TS2537: Type '{ bar: string; }' has no matching index signature for type 'string'.
[{[foo()]: bar4}] = [{bar: "bar"}];
~~~~~
!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures.
~~~~~
!!! error TS2538: Type 'any' cannot be used as an index type.
[{[(1 + {})]: bar4}] = [{bar: "bar"}];
~~~~~~~~
!!! error TS2538: Type 'any' cannot be used as an index type.
~~~~~~
!!! error TS2365: Operator '+' cannot be applied to types '1' and '{}'.
@@ -277,8 +277,8 @@ function f9() {
>{} : {}
var [c, d] = { 0: 10, 1: 20 }; // Error, not array type
>c : number
>d : number
>c : any
>d : any
>{ 0: 10, 1: 20 } : { 0: number; 1: number; }
>0 : number
>10 : 10
@@ -42,7 +42,7 @@ var [b3 = "string", b4, b5] = bar(); // Error
>b3 : string | Number
>"string" : "string"
>b4 : Number
>b5 : Number
>b5 : number
>bar() : J
>bar : () => J
@@ -0,0 +1,47 @@
tests/cases/conformance/es6/destructuring/destructuringControlFlow.ts(31,8): error TS2339: Property 'x' does not exist on type 'Number'.
tests/cases/conformance/es6/destructuring/destructuringControlFlow.ts(32,9): error TS2339: Property 'x' does not exist on type 'Number'.
tests/cases/conformance/es6/destructuring/destructuringControlFlow.ts(33,9): error TS2537: Type 'Number' has no matching index signature for type 'string'.
==== tests/cases/conformance/es6/destructuring/destructuringControlFlow.ts (3 errors) ====
function f1(obj: { a?: string }) {
if (obj.a) {
obj = {};
let a1 = obj["a"]; // string | undefined
let a2 = obj.a; // string | undefined
}
}
function f2(obj: [number, string] | null[]) {
let a0 = obj[0]; // number | null
let a1 = obj[1]; // string | null
let [b0, b1] = obj;
([a0, a1] = obj);
if (obj[0] && obj[1]) {
let c0 = obj[0]; // number
let c1 = obj[1]; // string
let [d0, d1] = obj;
([c0, c1] = obj);
}
}
function f3(obj: { a?: number, b?: string }) {
if (obj.a && obj.b) {
let { a, b } = obj; // number, string
({ a, b } = obj);
}
}
function f4() {
let x: boolean;
({ x } = 0); // Error
~
!!! error TS2339: Property 'x' does not exist on type 'Number'.
({ ["x"]: x } = 0); // Error
~~~
!!! error TS2339: Property 'x' does not exist on type 'Number'.
({ ["x" + ""]: x } = 0); // Errpr
~~~~~~~~
!!! error TS2537: Type 'Number' has no matching index signature for type 'string'.
}
@@ -0,0 +1,71 @@
//// [destructuringControlFlow.ts]
function f1(obj: { a?: string }) {
if (obj.a) {
obj = {};
let a1 = obj["a"]; // string | undefined
let a2 = obj.a; // string | undefined
}
}
function f2(obj: [number, string] | null[]) {
let a0 = obj[0]; // number | null
let a1 = obj[1]; // string | null
let [b0, b1] = obj;
([a0, a1] = obj);
if (obj[0] && obj[1]) {
let c0 = obj[0]; // number
let c1 = obj[1]; // string
let [d0, d1] = obj;
([c0, c1] = obj);
}
}
function f3(obj: { a?: number, b?: string }) {
if (obj.a && obj.b) {
let { a, b } = obj; // number, string
({ a, b } = obj);
}
}
function f4() {
let x: boolean;
({ x } = 0); // Error
({ ["x"]: x } = 0); // Error
({ ["x" + ""]: x } = 0); // Errpr
}
//// [destructuringControlFlow.js]
"use strict";
function f1(obj) {
if (obj.a) {
obj = {};
var a1 = obj["a"]; // string | undefined
var a2 = obj.a; // string | undefined
}
}
function f2(obj) {
var a0 = obj[0]; // number | null
var a1 = obj[1]; // string | null
var b0 = obj[0], b1 = obj[1];
(a0 = obj[0], a1 = obj[1]);
if (obj[0] && obj[1]) {
var c0 = obj[0]; // number
var c1 = obj[1]; // string
var d0 = obj[0], d1 = obj[1];
(c0 = obj[0], c1 = obj[1]);
}
}
function f3(obj) {
if (obj.a && obj.b) {
var a = obj.a, b = obj.b; // number, string
(a = obj.a, b = obj.b);
}
}
function f4() {
var _a;
var x;
(x = 0..x); // Error
(x = 0["x"]); // Error
(_a = "x" + "", x = 0[_a]); // Errpr
}
@@ -0,0 +1,124 @@
=== tests/cases/conformance/es6/destructuring/destructuringControlFlow.ts ===
function f1(obj: { a?: string }) {
>f1 : Symbol(f1, Decl(destructuringControlFlow.ts, 0, 0))
>obj : Symbol(obj, Decl(destructuringControlFlow.ts, 0, 12))
>a : Symbol(a, Decl(destructuringControlFlow.ts, 0, 18))
if (obj.a) {
>obj.a : Symbol(a, Decl(destructuringControlFlow.ts, 0, 18))
>obj : Symbol(obj, Decl(destructuringControlFlow.ts, 0, 12))
>a : Symbol(a, Decl(destructuringControlFlow.ts, 0, 18))
obj = {};
>obj : Symbol(obj, Decl(destructuringControlFlow.ts, 0, 12))
let a1 = obj["a"]; // string | undefined
>a1 : Symbol(a1, Decl(destructuringControlFlow.ts, 3, 11))
>obj : Symbol(obj, Decl(destructuringControlFlow.ts, 0, 12))
>"a" : Symbol(a, Decl(destructuringControlFlow.ts, 0, 18))
let a2 = obj.a; // string | undefined
>a2 : Symbol(a2, Decl(destructuringControlFlow.ts, 4, 11))
>obj.a : Symbol(a, Decl(destructuringControlFlow.ts, 0, 18))
>obj : Symbol(obj, Decl(destructuringControlFlow.ts, 0, 12))
>a : Symbol(a, Decl(destructuringControlFlow.ts, 0, 18))
}
}
function f2(obj: [number, string] | null[]) {
>f2 : Symbol(f2, Decl(destructuringControlFlow.ts, 6, 1))
>obj : Symbol(obj, Decl(destructuringControlFlow.ts, 8, 12))
let a0 = obj[0]; // number | null
>a0 : Symbol(a0, Decl(destructuringControlFlow.ts, 9, 7))
>obj : Symbol(obj, Decl(destructuringControlFlow.ts, 8, 12))
>0 : Symbol(0)
let a1 = obj[1]; // string | null
>a1 : Symbol(a1, Decl(destructuringControlFlow.ts, 10, 7))
>obj : Symbol(obj, Decl(destructuringControlFlow.ts, 8, 12))
>1 : Symbol(1)
let [b0, b1] = obj;
>b0 : Symbol(b0, Decl(destructuringControlFlow.ts, 11, 9))
>b1 : Symbol(b1, Decl(destructuringControlFlow.ts, 11, 12))
>obj : Symbol(obj, Decl(destructuringControlFlow.ts, 8, 12))
([a0, a1] = obj);
>a0 : Symbol(a0, Decl(destructuringControlFlow.ts, 9, 7))
>a1 : Symbol(a1, Decl(destructuringControlFlow.ts, 10, 7))
>obj : Symbol(obj, Decl(destructuringControlFlow.ts, 8, 12))
if (obj[0] && obj[1]) {
>obj : Symbol(obj, Decl(destructuringControlFlow.ts, 8, 12))
>0 : Symbol(0)
>obj : Symbol(obj, Decl(destructuringControlFlow.ts, 8, 12))
>1 : Symbol(1)
let c0 = obj[0]; // number
>c0 : Symbol(c0, Decl(destructuringControlFlow.ts, 14, 11))
>obj : Symbol(obj, Decl(destructuringControlFlow.ts, 8, 12))
>0 : Symbol(0)
let c1 = obj[1]; // string
>c1 : Symbol(c1, Decl(destructuringControlFlow.ts, 15, 11))
>obj : Symbol(obj, Decl(destructuringControlFlow.ts, 8, 12))
>1 : Symbol(1)
let [d0, d1] = obj;
>d0 : Symbol(d0, Decl(destructuringControlFlow.ts, 16, 13))
>d1 : Symbol(d1, Decl(destructuringControlFlow.ts, 16, 16))
>obj : Symbol(obj, Decl(destructuringControlFlow.ts, 8, 12))
([c0, c1] = obj);
>c0 : Symbol(c0, Decl(destructuringControlFlow.ts, 14, 11))
>c1 : Symbol(c1, Decl(destructuringControlFlow.ts, 15, 11))
>obj : Symbol(obj, Decl(destructuringControlFlow.ts, 8, 12))
}
}
function f3(obj: { a?: number, b?: string }) {
>f3 : Symbol(f3, Decl(destructuringControlFlow.ts, 19, 1))
>obj : Symbol(obj, Decl(destructuringControlFlow.ts, 21, 12))
>a : Symbol(a, Decl(destructuringControlFlow.ts, 21, 18))
>b : Symbol(b, Decl(destructuringControlFlow.ts, 21, 30))
if (obj.a && obj.b) {
>obj.a : Symbol(a, Decl(destructuringControlFlow.ts, 21, 18))
>obj : Symbol(obj, Decl(destructuringControlFlow.ts, 21, 12))
>a : Symbol(a, Decl(destructuringControlFlow.ts, 21, 18))
>obj.b : Symbol(b, Decl(destructuringControlFlow.ts, 21, 30))
>obj : Symbol(obj, Decl(destructuringControlFlow.ts, 21, 12))
>b : Symbol(b, Decl(destructuringControlFlow.ts, 21, 30))
let { a, b } = obj; // number, string
>a : Symbol(a, Decl(destructuringControlFlow.ts, 23, 13))
>b : Symbol(b, Decl(destructuringControlFlow.ts, 23, 16))
>obj : Symbol(obj, Decl(destructuringControlFlow.ts, 21, 12))
({ a, b } = obj);
>a : Symbol(a, Decl(destructuringControlFlow.ts, 24, 10))
>b : Symbol(b, Decl(destructuringControlFlow.ts, 24, 13))
>obj : Symbol(obj, Decl(destructuringControlFlow.ts, 21, 12))
}
}
function f4() {
>f4 : Symbol(f4, Decl(destructuringControlFlow.ts, 26, 1))
let x: boolean;
>x : Symbol(x, Decl(destructuringControlFlow.ts, 29, 7))
({ x } = 0); // Error
>x : Symbol(x, Decl(destructuringControlFlow.ts, 30, 6))
({ ["x"]: x } = 0); // Error
>["x"] : Symbol(["x"], Decl(destructuringControlFlow.ts, 31, 6))
>"x" : Symbol(["x"], Decl(destructuringControlFlow.ts, 31, 6))
>x : Symbol(x, Decl(destructuringControlFlow.ts, 29, 7))
({ ["x" + ""]: x } = 0); // Errpr
>["x" + ""] : Symbol(["x" + ""], Decl(destructuringControlFlow.ts, 32, 6))
>x : Symbol(x, Decl(destructuringControlFlow.ts, 29, 7))
}
@@ -0,0 +1,160 @@
=== tests/cases/conformance/es6/destructuring/destructuringControlFlow.ts ===
function f1(obj: { a?: string }) {
>f1 : (obj: { a?: string | undefined; }) => void
>obj : { a?: string | undefined; }
>a : string | undefined
if (obj.a) {
>obj.a : string | undefined
>obj : { a?: string | undefined; }
>a : string | undefined
obj = {};
>obj = {} : {}
>obj : { a?: string | undefined; }
>{} : {}
let a1 = obj["a"]; // string | undefined
>a1 : string | undefined
>obj["a"] : string | undefined
>obj : { a?: string | undefined; }
>"a" : "a"
let a2 = obj.a; // string | undefined
>a2 : string | undefined
>obj.a : string | undefined
>obj : { a?: string | undefined; }
>a : string | undefined
}
}
function f2(obj: [number, string] | null[]) {
>f2 : (obj: [number, string] | null[]) => void
>obj : [number, string] | null[]
>null : null
let a0 = obj[0]; // number | null
>a0 : number | null
>obj[0] : number | null
>obj : [number, string] | null[]
>0 : 0
let a1 = obj[1]; // string | null
>a1 : string | null
>obj[1] : string | null
>obj : [number, string] | null[]
>1 : 1
let [b0, b1] = obj;
>b0 : number | null
>b1 : string | null
>obj : [number, string] | null[]
([a0, a1] = obj);
>([a0, a1] = obj) : [number, string] | null[]
>[a0, a1] = obj : [number, string] | null[]
>[a0, a1] : [number | null, string | null]
>a0 : number | null
>a1 : string | null
>obj : [number, string] | null[]
if (obj[0] && obj[1]) {
>obj[0] && obj[1] : string | 0 | null
>obj[0] : number | null
>obj : [number, string] | null[]
>0 : 0
>obj[1] : string | null
>obj : [number, string] | null[]
>1 : 1
let c0 = obj[0]; // number
>c0 : number
>obj[0] : number
>obj : [number, string] | null[]
>0 : 0
let c1 = obj[1]; // string
>c1 : string
>obj[1] : string
>obj : [number, string] | null[]
>1 : 1
let [d0, d1] = obj;
>d0 : number
>d1 : string
>obj : [number, string] | null[]
([c0, c1] = obj);
>([c0, c1] = obj) : [number, string] | null[]
>[c0, c1] = obj : [number, string] | null[]
>[c0, c1] : [number, string]
>c0 : number
>c1 : string
>obj : [number, string] | null[]
}
}
function f3(obj: { a?: number, b?: string }) {
>f3 : (obj: { a?: number | undefined; b?: string | undefined; }) => void
>obj : { a?: number | undefined; b?: string | undefined; }
>a : number | undefined
>b : string | undefined
if (obj.a && obj.b) {
>obj.a && obj.b : string | 0 | undefined
>obj.a : number | undefined
>obj : { a?: number | undefined; b?: string | undefined; }
>a : number | undefined
>obj.b : string | undefined
>obj : { a?: number | undefined; b?: string | undefined; }
>b : string | undefined
let { a, b } = obj; // number, string
>a : number
>b : string
>obj : { a?: number | undefined; b?: string | undefined; }
({ a, b } = obj);
>({ a, b } = obj) : { a?: number | undefined; b?: string | undefined; }
>{ a, b } = obj : { a?: number | undefined; b?: string | undefined; }
>{ a, b } : { a: number; b: string; }
>a : number
>b : string
>obj : { a?: number | undefined; b?: string | undefined; }
}
}
function f4() {
>f4 : () => void
let x: boolean;
>x : boolean
({ x } = 0); // Error
>({ x } = 0) : 0
>{ x } = 0 : 0
>{ x } : { x: boolean; }
>x : boolean
>0 : 0
({ ["x"]: x } = 0); // Error
>({ ["x"]: x } = 0) : 0
>{ ["x"]: x } = 0 : 0
>{ ["x"]: x } : { ["x"]: boolean; }
>["x"] : boolean
>"x" : "x"
>x : boolean
>0 : 0
({ ["x" + ""]: x } = 0); // Errpr
>({ ["x" + ""]: x } = 0) : 0
>{ ["x" + ""]: x } = 0 : 0
>{ ["x" + ""]: x } : { [x: string]: boolean; }
>["x" + ""] : boolean
>"x" + "" : string
>"x" : "x"
>"" : ""
>x : boolean
>0 : 0
}
@@ -1,5 +1,5 @@
tests/cases/compiler/emitCapturingThisInTupleDestructuring1.ts(3,17): error TS2493: Tuple type '[any]' with length '1' cannot be assigned to tuple with length '3'.
tests/cases/compiler/emitCapturingThisInTupleDestructuring1.ts(3,29): error TS2493: Tuple type '[any]' with length '1' cannot be assigned to tuple with length '3'.
tests/cases/compiler/emitCapturingThisInTupleDestructuring1.ts(3,17): error TS2493: Tuple type '[any]' of length '1' has no element at index '1'.
tests/cases/compiler/emitCapturingThisInTupleDestructuring1.ts(3,29): error TS2493: Tuple type '[any]' of length '1' has no element at index '2'.
==== tests/cases/compiler/emitCapturingThisInTupleDestructuring1.ts (2 errors) ====
@@ -7,7 +7,7 @@ tests/cases/compiler/emitCapturingThisInTupleDestructuring1.ts(3,29): error TS24
wrapper((array: [any]) => {
[this.test, this.test1, this.test2] = array; // even though there is a compiler error, we should still emit lexical capture for "this"
~~~~~~~~~~
!!! error TS2493: Tuple type '[any]' with length '1' cannot be assigned to tuple with length '3'.
!!! error TS2493: Tuple type '[any]' of length '1' has no element at index '1'.
~~~~~~~~~~
!!! error TS2493: Tuple type '[any]' with length '1' cannot be assigned to tuple with length '3'.
!!! error TS2493: Tuple type '[any]' of length '1' has no element at index '2'.
});
@@ -1,4 +1,4 @@
tests/cases/compiler/emitCapturingThisInTupleDestructuring2.ts(8,39): error TS2493: Tuple type '[number, number]' with length '2' cannot be assigned to tuple with length '3'.
tests/cases/compiler/emitCapturingThisInTupleDestructuring2.ts(8,39): error TS2493: Tuple type '[number, number]' of length '2' has no element at index '2'.
==== tests/cases/compiler/emitCapturingThisInTupleDestructuring2.ts (1 errors) ====
@@ -11,6 +11,6 @@ tests/cases/compiler/emitCapturingThisInTupleDestructuring2.ts(8,39): error TS24
method() {
() => [this.test, this.test1, this.test2] = array1; // even though there is a compiler error, we should still emit lexical capture for "this"
~~~~~~~~~~
!!! error TS2493: Tuple type '[number, number]' with length '2' cannot be assigned to tuple with length '3'.
!!! error TS2493: Tuple type '[number, number]' of length '2' has no element at index '2'.
}
}
@@ -1,8 +1,8 @@
tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion01.ts(2,11): error TS2339: Property '0' does not exist on type '[]'.
tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion01.ts(2,11): error TS2493: Tuple type '[]' of length '0' has no element at index '0'.
==== tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion01.ts (1 errors) ====
let x = <[]>[];
let y = x[0];
~
!!! error TS2339: Property '0' does not exist on type '[]'.
!!! error TS2493: Tuple type '[]' of length '0' has no element at index '0'.
@@ -1,8 +1,8 @@
tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion02.ts(2,11): error TS2339: Property '0' does not exist on type '[]'.
tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion02.ts(2,11): error TS2493: Tuple type '[]' of length '0' has no element at index '0'.
==== tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion02.ts (1 errors) ====
let x = [] as [];
let y = x[0];
~
!!! error TS2339: Property '0' does not exist on type '[]'.
!!! error TS2493: Tuple type '[]' of length '0' has no element at index '0'.
@@ -1,10 +1,10 @@
tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTupleType.ts(12,1): error TS2322: Type '[string, number, boolean, boolean]' is not assignable to type '[string, number]'.
Types of property 'length' are incompatible.
Type '4' is not assignable to type '2'.
tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTupleType.ts(13,20): error TS2339: Property '2' does not exist on type '[string, number]'.
tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTupleType.ts(13,20): error TS2493: Tuple type '[string, number]' of length '2' has no element at index '2'.
tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTupleType.ts(14,1): error TS2322: Type '{ a: string; }' is not assignable to type 'undefined'.
tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTupleType.ts(14,11): error TS2339: Property '3' does not exist on type '[string, number]'.
tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTupleType.ts(15,20): error TS2339: Property '3' does not exist on type '[string, number]'.
tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTupleType.ts(14,11): error TS2493: Tuple type '[string, number]' of length '2' has no element at index '3'.
tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTupleType.ts(15,20): error TS2493: Tuple type '[string, number]' of length '2' has no element at index '3'.
tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTupleType.ts(22,14): error TS2322: Type 'number' is not assignable to type 'string'.
tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTupleType.ts(22,17): error TS2322: Type 'string' is not assignable to type 'number'.
tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTupleType.ts(23,14): error TS2322: Type '{}' is not assignable to type 'string'.
@@ -31,15 +31,15 @@ tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTup
!!! error TS2322: Type '4' is not assignable to type '2'.
var e3 = i1.tuple1[2]; // {}
~
!!! error TS2339: Property '2' does not exist on type '[string, number]'.
!!! error TS2493: Tuple type '[string, number]' of length '2' has no element at index '2'.
i1.tuple1[3] = { a: "string" };
~~~~~~~~~~~~
!!! error TS2322: Type '{ a: string; }' is not assignable to type 'undefined'.
~
!!! error TS2339: Property '3' does not exist on type '[string, number]'.
!!! error TS2493: Tuple type '[string, number]' of length '2' has no element at index '3'.
var e4 = i1.tuple1[3]; // {}
~
!!! error TS2339: Property '3' does not exist on type '[string, number]'.
!!! error TS2493: Tuple type '[string, number]' of length '2' has no element at index '3'.
i2.tuple1 = ["foo", 5];
i2.tuple1 = ["foo", "bar"];
i2.tuple1 = [5, "bar"];
@@ -1,7 +1,7 @@
tests/cases/conformance/types/tuple/indexerWithTuple.ts(11,25): error TS2339: Property '2' does not exist on type '[string, number]'.
tests/cases/conformance/types/tuple/indexerWithTuple.ts(17,27): error TS2339: Property '2' does not exist on type '[number, [string, number]]'.
tests/cases/conformance/types/tuple/indexerWithTuple.ts(20,30): error TS2339: Property '2' does not exist on type '[number, string | number]'.
tests/cases/conformance/types/tuple/indexerWithTuple.ts(28,30): error TS2339: Property '2' does not exist on type '[boolean, string | number]'.
tests/cases/conformance/types/tuple/indexerWithTuple.ts(11,25): error TS2493: Tuple type '[string, number]' of length '2' has no element at index '2'.
tests/cases/conformance/types/tuple/indexerWithTuple.ts(17,27): error TS2493: Tuple type '[number, [string, number]]' of length '2' has no element at index '2'.
tests/cases/conformance/types/tuple/indexerWithTuple.ts(20,30): error TS2493: Tuple type '[number, string | number]' of length '2' has no element at index '2'.
tests/cases/conformance/types/tuple/indexerWithTuple.ts(28,30): error TS2493: Tuple type '[boolean, string | number]' of length '2' has no element at index '2'.
==== tests/cases/conformance/types/tuple/indexerWithTuple.ts (4 errors) ====
@@ -17,7 +17,7 @@ tests/cases/conformance/types/tuple/indexerWithTuple.ts(28,30): error TS2339: Pr
var ele11 = strNumTuple[1]; // number
var ele12 = strNumTuple[2]; // string | number
~
!!! error TS2339: Property '2' does not exist on type '[string, number]'.
!!! error TS2493: Tuple type '[string, number]' of length '2' has no element at index '2'.
var ele13 = strNumTuple[idx0]; // string | number
var ele14 = strNumTuple[idx1]; // string | number
var ele15 = strNumTuple["0"]; // string
@@ -25,12 +25,12 @@ tests/cases/conformance/types/tuple/indexerWithTuple.ts(28,30): error TS2339: Pr
var strNumTuple1 = numTupleTuple[1]; //[string, number];
var ele17 = numTupleTuple[2]; // number | [string, number]
~
!!! error TS2339: Property '2' does not exist on type '[number, [string, number]]'.
!!! error TS2493: Tuple type '[number, [string, number]]' of length '2' has no element at index '2'.
var eleUnion10 = unionTuple1[0]; // number
var eleUnion11 = unionTuple1[1]; // string | number
var eleUnion12 = unionTuple1[2]; // string | number
~
!!! error TS2339: Property '2' does not exist on type '[number, string | number]'.
!!! error TS2493: Tuple type '[number, string | number]' of length '2' has no element at index '2'.
var eleUnion13 = unionTuple1[idx0]; // string | number
var eleUnion14 = unionTuple1[idx1]; // string | number
var eleUnion15 = unionTuple1["0"]; // number
@@ -40,7 +40,7 @@ tests/cases/conformance/types/tuple/indexerWithTuple.ts(28,30): error TS2339: Pr
var eleUnion21 = unionTuple2[1]; // string | number
var eleUnion22 = unionTuple2[2]; // string | number | boolean
~
!!! error TS2339: Property '2' does not exist on type '[boolean, string | number]'.
!!! error TS2493: Tuple type '[boolean, string | number]' of length '2' has no element at index '2'.
var eleUnion23 = unionTuple2[idx0]; // string | number | boolean
var eleUnion24 = unionTuple2[idx1]; // string | number | boolean
var eleUnion25 = unionTuple2["0"]; // boolean
@@ -1,7 +1,7 @@
=== tests/cases/conformance/es6/destructuring/iterableArrayPattern21.ts ===
var [a, b] = { 0: "", 1: true };
>a : string
>b : boolean
>a : any
>b : any
>{ 0: "", 1: true } : { 0: string; 1: boolean; }
>0 : string
>"" : ""
@@ -3,10 +3,12 @@ tests/cases/conformance/types/rest/objectRest.ts(7,20): error TS2339: Property '
tests/cases/conformance/types/rest/objectRest.ts(43,8): error TS2537: Type '{ a: number; b: string; }' has no matching index signature for type 'string'.
tests/cases/conformance/types/rest/objectRest.ts(43,35): error TS2537: Type '{ a: number; b: string; }' has no matching index signature for type 'string'.
tests/cases/conformance/types/rest/objectRest.ts(43,57): error TS2403: Subsequent variable declarations must have the same type. Variable 'o' must be of type '{ a: number; b: string; }', but here has type '{}'.
tests/cases/conformance/types/rest/objectRest.ts(44,5): error TS2537: Type '{ a: number; b: string; }' has no matching index signature for type 'string'.
tests/cases/conformance/types/rest/objectRest.ts(44,32): error TS2537: Type '{ a: number; b: string; }' has no matching index signature for type 'string'.
tests/cases/conformance/types/rest/objectRest.ts(44,53): error TS2739: Type '{}' is missing the following properties from type '{ a: number; b: string; }': a, b
==== tests/cases/conformance/types/rest/objectRest.ts (6 errors) ====
==== tests/cases/conformance/types/rest/objectRest.ts (8 errors) ====
var o = { a: 1, b: 'no' }
var { ...clone } = o;
var { a, ...justB } = o;
@@ -61,6 +63,10 @@ tests/cases/conformance/types/rest/objectRest.ts(44,53): error TS2739: Type '{}'
~
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'o' must be of type '{ a: number; b: string; }', but here has type '{}'.
({ [computed]: stillNotGreat, [computed2]: soSo, ...o } = o);
~~~~~~~~
!!! error TS2537: Type '{ a: number; b: string; }' has no matching index signature for type 'string'.
~~~~~~~~~
!!! error TS2537: Type '{ a: number; b: string; }' has no matching index signature for type 'string'.
~
!!! error TS2739: Type '{}' is missing the following properties from type '{ a: number; b: string; }': a, b
@@ -1,6 +1,6 @@
tests/cases/conformance/es6/destructuring/restElementWithAssignmentPattern2.ts(2,10): error TS2322: Type 'string | number' is not assignable to type 'string'.
Type 'number' is not assignable to type 'string'.
tests/cases/conformance/es6/destructuring/restElementWithAssignmentPattern2.ts(2,18): error TS2459: Type '(string | number)[]' has no property 'b' and no string index signature.
tests/cases/conformance/es6/destructuring/restElementWithAssignmentPattern2.ts(2,18): error TS2339: Property 'b' does not exist on type '(string | number)[]'.
==== tests/cases/conformance/es6/destructuring/restElementWithAssignmentPattern2.ts (2 errors) ====
@@ -10,4 +10,4 @@ tests/cases/conformance/es6/destructuring/restElementWithAssignmentPattern2.ts(2
!!! error TS2322: Type 'string | number' is not assignable to type 'string'.
!!! error TS2322: Type 'number' is not assignable to type 'string'.
~
!!! error TS2459: Type '(string | number)[]' has no property 'b' and no string index signature.
!!! error TS2339: Property 'b' does not exist on type '(string | number)[]'.
@@ -1,4 +1,4 @@
tests/cases/conformance/es6/destructuring/restElementWithAssignmentPattern4.ts(3,18): error TS2459: Type '[string, number]' has no property 'b' and no string index signature.
tests/cases/conformance/es6/destructuring/restElementWithAssignmentPattern4.ts(3,18): error TS2339: Property 'b' does not exist on type '[string, number]'.
==== tests/cases/conformance/es6/destructuring/restElementWithAssignmentPattern4.ts (1 errors) ====
@@ -6,4 +6,4 @@ tests/cases/conformance/es6/destructuring/restElementWithAssignmentPattern4.ts(3
var tuple: [string, number] = ["", 1];
[...{ 0: a = "", b }] = tuple;
~
!!! error TS2459: Type '[string, number]' has no property 'b' and no string index signature.
!!! error TS2339: Property 'b' does not exist on type '[string, number]'.
@@ -1,5 +1,5 @@
tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring.ts(14,9): error TS2459: Type '{}' has no property 's1' and no string index signature.
tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring.ts(20,9): error TS2459: Type '{}' has no property 's1' and no string index signature.
tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring.ts(14,9): error TS2339: Property 's1' does not exist on type '{}'.
tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring.ts(20,9): error TS2339: Property 's1' does not exist on type '{}'.
tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring.ts(38,9): error TS2322: Type '5' is not assignable to type 'string'.
tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring.ts(44,12): error TS2322: Type '5' is not assignable to type 'string'.
tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring.ts(70,5): error TS2322: Type '5' is not assignable to type 'string'.
@@ -33,7 +33,7 @@ tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring.ts(111,14): err
var s1;
for ({ s1 = 5 } of [{}]) {
~~
!!! error TS2459: Type '{}' has no property 's1' and no string index signature.
!!! error TS2339: Property 's1' does not exist on type '{}'.
}
});
@@ -41,7 +41,7 @@ tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring.ts(111,14): err
var s1;
for ({ s1:s1 = 5 } of [{}]) {
~~
!!! error TS2459: Type '{}' has no property 's1' and no string index signature.
!!! error TS2339: Property 's1' does not exist on type '{}'.
}
});
@@ -1,5 +1,5 @@
tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring_ES6.ts(14,9): error TS2459: Type '{}' has no property 's1' and no string index signature.
tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring_ES6.ts(20,9): error TS2459: Type '{}' has no property 's1' and no string index signature.
tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring_ES6.ts(14,9): error TS2339: Property 's1' does not exist on type '{}'.
tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring_ES6.ts(20,9): error TS2339: Property 's1' does not exist on type '{}'.
tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring_ES6.ts(38,9): error TS2322: Type '5' is not assignable to type 'string'.
tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring_ES6.ts(44,12): error TS2322: Type '5' is not assignable to type 'string'.
tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring_ES6.ts(70,5): error TS2322: Type '5' is not assignable to type 'string'.
@@ -33,7 +33,7 @@ tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring_ES6.ts(111,14):
var s1;
for ({ s1 = 5 } of [{}]) {
~~
!!! error TS2459: Type '{}' has no property 's1' and no string index signature.
!!! error TS2339: Property 's1' does not exist on type '{}'.
}
});
@@ -41,7 +41,7 @@ tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring_ES6.ts(111,14):
var s1;
for ({ s1:s1 = 5 } of [{}]) {
~~
!!! error TS2459: Type '{}' has no property 's1' and no string index signature.
!!! error TS2339: Property 's1' does not exist on type '{}'.
}
});
@@ -1,5 +1,5 @@
tests/cases/conformance/types/tuple/tupleLengthCheck.ts(5,14): error TS2339: Property '2' does not exist on type '[number, string]'.
tests/cases/conformance/types/tuple/tupleLengthCheck.ts(6,14): error TS2339: Property '1000' does not exist on type '[number, string]'.
tests/cases/conformance/types/tuple/tupleLengthCheck.ts(5,14): error TS2493: Tuple type '[number, string]' of length '2' has no element at index '2'.
tests/cases/conformance/types/tuple/tupleLengthCheck.ts(6,14): error TS2493: Tuple type '[number, string]' of length '2' has no element at index '1000'.
==== tests/cases/conformance/types/tuple/tupleLengthCheck.ts (2 errors) ====
@@ -9,10 +9,10 @@ tests/cases/conformance/types/tuple/tupleLengthCheck.ts(6,14): error TS2339: Pro
const a1 = a[1]
const a2 = a[2]
~
!!! error TS2339: Property '2' does not exist on type '[number, string]'.
!!! error TS2493: Tuple type '[number, string]' of length '2' has no element at index '2'.
const a3 = a[1000]
~~~~
!!! error TS2339: Property '1000' does not exist on type '[number, string]'.
!!! error TS2493: Tuple type '[number, string]' of length '2' has no element at index '1000'.
const a4 = rest[1]
const a5 = rest[2]
@@ -1,4 +1,4 @@
tests/cases/compiler/tupleTypes.ts(11,12): error TS2339: Property '2' does not exist on type '[number, string]'.
tests/cases/compiler/tupleTypes.ts(11,12): error TS2493: Tuple type '[number, string]' of length '2' has no element at index '2'.
tests/cases/compiler/tupleTypes.ts(12,5): error TS2403: Subsequent variable declarations must have the same type. Variable 't2' must be of type 'undefined', but here has type 'string | number'.
tests/cases/compiler/tupleTypes.ts(14,1): error TS2739: Type '[]' is missing the following properties from type '[number, string]': 0, 1
tests/cases/compiler/tupleTypes.ts(15,1): error TS2741: Property '1' is missing in type '[number]' but required in type '[number, string]'.
@@ -7,7 +7,7 @@ tests/cases/compiler/tupleTypes.ts(17,15): error TS2322: Type 'number' is not as
tests/cases/compiler/tupleTypes.ts(18,1): error TS2322: Type '[number, string, number]' is not assignable to type '[number, string]'.
Types of property 'length' are incompatible.
Type '3' is not assignable to type '2'.
tests/cases/compiler/tupleTypes.ts(35,14): error TS2339: Property '2' does not exist on type '[number, string]'.
tests/cases/compiler/tupleTypes.ts(35,14): error TS2493: Tuple type '[number, string]' of length '2' has no element at index '2'.
tests/cases/compiler/tupleTypes.ts(36,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'tt2' must be of type 'undefined', but here has type 'string | number'.
tests/cases/compiler/tupleTypes.ts(41,1): error TS2322: Type '[]' is not assignable to type '[number, string]'.
tests/cases/compiler/tupleTypes.ts(47,1): error TS2322: Type '[number, string]' is not assignable to type 'number[]'.
@@ -35,7 +35,7 @@ tests/cases/compiler/tupleTypes.ts(51,1): error TS2322: Type '[number, {}]' is n
var t1: string;
var t2 = t[2]; // number|string
~
!!! error TS2339: Property '2' does not exist on type '[number, string]'.
!!! error TS2493: Tuple type '[number, string]' of length '2' has no element at index '2'.
var t2: number|string;
~~
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 't2' must be of type 'undefined', but here has type 'string | number'.
@@ -75,7 +75,7 @@ tests/cases/compiler/tupleTypes.ts(51,1): error TS2322: Type '[number, {}]' is n
var tt1: string;
var tt2 = tt[2];
~
!!! error TS2339: Property '2' does not exist on type '[number, string]'.
!!! error TS2493: Tuple type '[number, string]' of length '2' has no element at index '2'.
var tt2: number | string;
~~~
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'tt2' must be of type 'undefined', but here has type 'string | number'.
@@ -1,10 +1,10 @@
tests/cases/conformance/types/tuple/unionsOfTupleTypes1.ts(8,15): error TS2339: Property '2' does not exist on type '[string, number]'.
tests/cases/conformance/types/tuple/unionsOfTupleTypes1.ts(8,15): error TS2493: Tuple type '[string, number]' of length '2' has no element at index '2'.
tests/cases/conformance/types/tuple/unionsOfTupleTypes1.ts(13,15): error TS2339: Property '2' does not exist on type 'T2'.
tests/cases/conformance/types/tuple/unionsOfTupleTypes1.ts(27,20): error TS2493: Tuple type '[string, number]' with length '2' cannot be assigned to tuple with length '3'.
tests/cases/conformance/types/tuple/unionsOfTupleTypes1.ts(28,20): error TS2460: Type 'T2' has no property '2'.
tests/cases/conformance/types/tuple/unionsOfTupleTypes1.ts(31,16): error TS2493: Tuple type '[string, number]' with length '2' cannot be assigned to tuple with length '3'.
tests/cases/conformance/types/tuple/unionsOfTupleTypes1.ts(32,16): error TS2460: Type 'T2' has no property '2'.
tests/cases/conformance/types/tuple/unionsOfTupleTypes1.ts(37,18): error TS2339: Property '2' does not exist on type '[string, number]'.
tests/cases/conformance/types/tuple/unionsOfTupleTypes1.ts(27,20): error TS2493: Tuple type '[string, number]' of length '2' has no element at index '2'.
tests/cases/conformance/types/tuple/unionsOfTupleTypes1.ts(28,20): error TS2339: Property '2' does not exist on type 'T2'.
tests/cases/conformance/types/tuple/unionsOfTupleTypes1.ts(31,16): error TS2493: Tuple type '[string, number]' of length '2' has no element at index '2'.
tests/cases/conformance/types/tuple/unionsOfTupleTypes1.ts(32,16): error TS2339: Property '2' does not exist on type 'T2'.
tests/cases/conformance/types/tuple/unionsOfTupleTypes1.ts(37,18): error TS2493: Tuple type '[string, number]' of length '2' has no element at index '2'.
tests/cases/conformance/types/tuple/unionsOfTupleTypes1.ts(41,18): error TS2339: Property '2' does not exist on type 'T2'.
@@ -18,7 +18,7 @@ tests/cases/conformance/types/tuple/unionsOfTupleTypes1.ts(41,18): error TS2339:
type T11 = T1[1]; // number
type T12 = T1[2]; // undefined
~
!!! error TS2339: Property '2' does not exist on type '[string, number]'.
!!! error TS2493: Tuple type '[string, number]' of length '2' has no element at index '2'.
type T1N = T1[number]; // string | number
type T20 = T2[0]; // string | boolean
@@ -41,25 +41,25 @@ tests/cases/conformance/types/tuple/unionsOfTupleTypes1.ts(41,18): error TS2339:
function f1(t1: T1, t2: T2, t3: T3, t4: T4, x: number) {
let [d10, d11, d12] = t1; // string, number
~~~
!!! error TS2493: Tuple type '[string, number]' with length '2' cannot be assigned to tuple with length '3'.
!!! error TS2493: Tuple type '[string, number]' of length '2' has no element at index '2'.
let [d20, d21, d22] = t2; // string | boolean, number | undefined
~~~
!!! error TS2460: Type 'T2' has no property '2'.
!!! error TS2339: Property '2' does not exist on type 'T2'.
let [d30, d31, d32] = t3; // string, number, number
let [d40, d41, d42] = t4; // string | boolean, number | undefined, number | undefined
[d10, d11, d12] = t1;
~~~
!!! error TS2493: Tuple type '[string, number]' with length '2' cannot be assigned to tuple with length '3'.
!!! error TS2493: Tuple type '[string, number]' of length '2' has no element at index '2'.
[d20, d21, d22] = t2;
~~~
!!! error TS2460: Type 'T2' has no property '2'.
!!! error TS2339: Property '2' does not exist on type 'T2'.
[d30, d31, d32] = t3;
[d40, d41, d42] = t4;
let t10 = t1[0]; // string
let t11 = t1[1]; // number
let t12 = t1[2]; // undefined
~
!!! error TS2339: Property '2' does not exist on type '[string, number]'.
!!! error TS2493: Tuple type '[string, number]' of length '2' has no element at index '2'.
let t1x = t1[x]; // string | number
let t20 = t2[0]; // string | boolean
let t21 = t2[1]; // number | undefined
@@ -70,13 +70,13 @@ function f1(t1: T1, t2: T2, t3: T3, t4: T4, x: number) {
let [d10, d11, d12] = t1; // string, number
>d10 : string
>d11 : number
>d12 : any
>d12 : undefined
>t1 : [string, number]
let [d20, d21, d22] = t2; // string | boolean, number | undefined
>d20 : string | boolean
>d21 : number | undefined
>d22 : any
>d22 : undefined
>t2 : T2
let [d30, d31, d32] = t3; // string, number, number
@@ -93,18 +93,18 @@ function f1(t1: T1, t2: T2, t3: T3, t4: T4, x: number) {
[d10, d11, d12] = t1;
>[d10, d11, d12] = t1 : [string, number]
>[d10, d11, d12] : [string, number, any]
>[d10, d11, d12] : [string, number, undefined]
>d10 : string
>d11 : number
>d12 : any
>d12 : undefined
>t1 : [string, number]
[d20, d21, d22] = t2;
>[d20, d21, d22] = t2 : T2
>[d20, d21, d22] : [string | boolean, number | undefined, any]
>[d20, d21, d22] : [string | boolean, number | undefined, undefined]
>d20 : string | boolean
>d21 : number | undefined
>d22 : any
>d22 : undefined
>t2 : T2
[d30, d31, d32] = t3;
@@ -0,0 +1,36 @@
// @strict: true
function f1(obj: { a?: string }) {
if (obj.a) {
obj = {};
let a1 = obj["a"]; // string | undefined
let a2 = obj.a; // string | undefined
}
}
function f2(obj: [number, string] | null[]) {
let a0 = obj[0]; // number | null
let a1 = obj[1]; // string | null
let [b0, b1] = obj;
([a0, a1] = obj);
if (obj[0] && obj[1]) {
let c0 = obj[0]; // number
let c1 = obj[1]; // string
let [d0, d1] = obj;
([c0, c1] = obj);
}
}
function f3(obj: { a?: number, b?: string }) {
if (obj.a && obj.b) {
let { a, b } = obj; // number, string
({ a, b } = obj);
}
}
function f4() {
let x: boolean;
({ x } = 0); // Error
({ ["x"]: x } = 0); // Error
({ ["x" + ""]: x } = 0); // Errpr
}