Contextual typing of array literals is now based on the presence or absence

of numerically named properties and doesn't directly test for tuple types.
This commit is contained in:
Anders Hejlsberg 2014-08-16 12:06:51 -07:00
parent c0e802deb5
commit 63b83e7c3f
3 changed files with 37 additions and 30 deletions

View File

@ -3758,19 +3758,17 @@ module ts {
return undefined;
}
// In an array literal contextually typed by a type T, the contextual type of an element expression is the corresponding
// tuple element type in T, if one exists and T is a tuple type. Otherwise, it is the type of the numeric index signature
// in T, if one exists.
// In an array literal contextually typed by a type T, the contextual type of an element expression at index N is
// the type of the property with the numeric name N in T, if one exists. Otherwise, it is the type of the numeric
// index signature in T, if one exists.
function getContextualTypeForElementExpression(node: Expression): Type {
var arrayLiteral = <ArrayLiteral>node.parent;
var type = getContextualType(arrayLiteral);
if (type) {
if (type.flags & TypeFlags.Tuple) {
var index = indexOf(arrayLiteral.elements, node);
var prop = getPropertyOfType(type, "" + index);
if (prop) {
return getTypeOfSymbol(prop);
}
var index = indexOf(arrayLiteral.elements, node);
var prop = getPropertyOfType(type, "" + index);
if (prop) {
return getTypeOfSymbol(prop);
}
return getIndexTypeOfType(type, IndexKind.Number);
}
@ -3837,21 +3835,24 @@ module ts {
function checkArrayLiteral(node: ArrayLiteral, contextualMapper?: TypeMapper): Type {
var contextualType = getContextualType(node);
var isTupleLiteral = contextualType && (contextualType.flags & TypeFlags.Tuple) !== 0;
var elements = node.elements;
var elementTypes: Type[] = [];
forEach(node.elements, element => {
var type = element.kind !== SyntaxKind.OmittedExpression ? checkExpression(element, contextualMapper) : undefinedType;
if (isTupleLiteral || !contains(elementTypes, type)) {
elementTypes.push(type);
var isTupleLiteral: boolean = false;
for (var i = 0; i < elements.length; i++) {
if (contextualType && getPropertyOfType(contextualType, "" + i)) {
isTupleLiteral = true;
}
});
var element = elements[i];
var type = element.kind !== SyntaxKind.OmittedExpression ? checkExpression(element, contextualMapper) : undefinedType;
elementTypes.push(type);
}
if (isTupleLiteral) {
return createTupleType(elementTypes);
}
var contextualElementType = contextualType && !isInferentialContext(contextualMapper) ? getIndexTypeOfType(contextualType, IndexKind.Number) : undefined;
var elementType = getBestCommonType(elementTypes, contextualElementType, true);
var elementType = getBestCommonType(uniqueElements(elementTypes), contextualElementType, true);
if (!elementType) {
elementType = elementTypes.length ? emptyObjectType : undefinedType;
elementType = elements.length ? emptyObjectType : undefinedType;
}
return createArrayType(elementType);
}

View File

@ -19,8 +19,7 @@ module ts {
export function contains<T>(array: T[], value: T): boolean {
if (array) {
var len = array.length;
for (var i = 0; i < len; i++) {
for (var i = 0, len = array.length; i < len; i++) {
if (array[i] === value) {
return true;
}
@ -31,8 +30,7 @@ module ts {
export function indexOf<T>(array: T[], value: T): number {
if (array) {
var len = array.length;
for (var i = 0; i < len; i++) {
for (var i = 0, len = array.length; i < len; i++) {
if (array[i] === value) {
return i;
}
@ -42,9 +40,8 @@ module ts {
}
export function filter<T>(array: T[], f: (x: T) => boolean): T[] {
var result: T[];
if (array) {
result = [];
var result: T[] = [];
for (var i = 0, len = array.length; i < len; i++) {
var item = array[i];
if (f(item)) {
@ -56,11 +53,9 @@ module ts {
}
export function map<T, U>(array: T[], f: (x: T) => U): U[] {
var result: U[];
if (array) {
result = [];
var len = array.length;
for (var i = 0; i < len; i++) {
var result: U[] = [];
for (var i = 0, len = array.length; i < len; i++) {
result.push(f(array[i]));
}
}
@ -73,6 +68,17 @@ module ts {
return array1.concat(array2);
}
export function uniqueElements<T>(array: T[]): T[] {
if (array) {
var result: T[] = [];
for (var i = 0, len = array.length; i < len; i++) {
var item = array[i];
if (!contains(result, item)) result.push(item);
}
}
return result;
}
export function sum(array: any[], prop: string): number {
var result = 0;
for (var i = 0; i < array.length; i++) {

View File

@ -16,8 +16,8 @@
t = []; // Error
~
!!! Type '[]' is not assignable to type '[number, string]':
!!! Property '0' is missing in type '[]'.
!!! Type '{}[]' is not assignable to type '[number, string]':
!!! Property '0' is missing in type '{}[]'.
t = [1]; // Error
~
!!! Type '[number]' is not assignable to type '[number, string]':
@ -53,7 +53,7 @@
tt = [undefined, undefined];
tt = []; // Error
~~
!!! Type '[]' is not assignable to type '[number, string]'.
!!! Type '{}[]' is not assignable to type '[number, string]'.
var a: number[];
var a1: [number, string];