Skip to content

Commit 63b83e7

Browse files
committed
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.
1 parent c0e802d commit 63b83e7

File tree

3 files changed

+37
-30
lines changed

3 files changed

+37
-30
lines changed

src/compiler/checker.ts

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3758,19 +3758,17 @@ module ts {
37583758
return undefined;
37593759
}
37603760

3761-
// In an array literal contextually typed by a type T, the contextual type of an element expression is the corresponding
3762-
// tuple element type in T, if one exists and T is a tuple type. Otherwise, it is the type of the numeric index signature
3763-
// in T, if one exists.
3761+
// In an array literal contextually typed by a type T, the contextual type of an element expression at index N is
3762+
// the type of the property with the numeric name N in T, if one exists. Otherwise, it is the type of the numeric
3763+
// index signature in T, if one exists.
37643764
function getContextualTypeForElementExpression(node: Expression): Type {
37653765
var arrayLiteral = <ArrayLiteral>node.parent;
37663766
var type = getContextualType(arrayLiteral);
37673767
if (type) {
3768-
if (type.flags & TypeFlags.Tuple) {
3769-
var index = indexOf(arrayLiteral.elements, node);
3770-
var prop = getPropertyOfType(type, "" + index);
3771-
if (prop) {
3772-
return getTypeOfSymbol(prop);
3773-
}
3768+
var index = indexOf(arrayLiteral.elements, node);
3769+
var prop = getPropertyOfType(type, "" + index);
3770+
if (prop) {
3771+
return getTypeOfSymbol(prop);
37743772
}
37753773
return getIndexTypeOfType(type, IndexKind.Number);
37763774
}
@@ -3837,21 +3835,24 @@ module ts {
38373835

38383836
function checkArrayLiteral(node: ArrayLiteral, contextualMapper?: TypeMapper): Type {
38393837
var contextualType = getContextualType(node);
3840-
var isTupleLiteral = contextualType && (contextualType.flags & TypeFlags.Tuple) !== 0;
3838+
var elements = node.elements;
38413839
var elementTypes: Type[] = [];
3842-
forEach(node.elements, element => {
3843-
var type = element.kind !== SyntaxKind.OmittedExpression ? checkExpression(element, contextualMapper) : undefinedType;
3844-
if (isTupleLiteral || !contains(elementTypes, type)) {
3845-
elementTypes.push(type);
3840+
var isTupleLiteral: boolean = false;
3841+
for (var i = 0; i < elements.length; i++) {
3842+
if (contextualType && getPropertyOfType(contextualType, "" + i)) {
3843+
isTupleLiteral = true;
38463844
}
3847-
});
3845+
var element = elements[i];
3846+
var type = element.kind !== SyntaxKind.OmittedExpression ? checkExpression(element, contextualMapper) : undefinedType;
3847+
elementTypes.push(type);
3848+
}
38483849
if (isTupleLiteral) {
38493850
return createTupleType(elementTypes);
38503851
}
38513852
var contextualElementType = contextualType && !isInferentialContext(contextualMapper) ? getIndexTypeOfType(contextualType, IndexKind.Number) : undefined;
3852-
var elementType = getBestCommonType(elementTypes, contextualElementType, true);
3853+
var elementType = getBestCommonType(uniqueElements(elementTypes), contextualElementType, true);
38533854
if (!elementType) {
3854-
elementType = elementTypes.length ? emptyObjectType : undefinedType;
3855+
elementType = elements.length ? emptyObjectType : undefinedType;
38553856
}
38563857
return createArrayType(elementType);
38573858
}

src/compiler/core.ts

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ module ts {
1919

2020
export function contains<T>(array: T[], value: T): boolean {
2121
if (array) {
22-
var len = array.length;
23-
for (var i = 0; i < len; i++) {
22+
for (var i = 0, len = array.length; i < len; i++) {
2423
if (array[i] === value) {
2524
return true;
2625
}
@@ -31,8 +30,7 @@ module ts {
3130

3231
export function indexOf<T>(array: T[], value: T): number {
3332
if (array) {
34-
var len = array.length;
35-
for (var i = 0; i < len; i++) {
33+
for (var i = 0, len = array.length; i < len; i++) {
3634
if (array[i] === value) {
3735
return i;
3836
}
@@ -42,9 +40,8 @@ module ts {
4240
}
4341

4442
export function filter<T>(array: T[], f: (x: T) => boolean): T[] {
45-
var result: T[];
4643
if (array) {
47-
result = [];
44+
var result: T[] = [];
4845
for (var i = 0, len = array.length; i < len; i++) {
4946
var item = array[i];
5047
if (f(item)) {
@@ -56,11 +53,9 @@ module ts {
5653
}
5754

5855
export function map<T, U>(array: T[], f: (x: T) => U): U[] {
59-
var result: U[];
6056
if (array) {
61-
result = [];
62-
var len = array.length;
63-
for (var i = 0; i < len; i++) {
57+
var result: U[] = [];
58+
for (var i = 0, len = array.length; i < len; i++) {
6459
result.push(f(array[i]));
6560
}
6661
}
@@ -73,6 +68,17 @@ module ts {
7368
return array1.concat(array2);
7469
}
7570

71+
export function uniqueElements<T>(array: T[]): T[] {
72+
if (array) {
73+
var result: T[] = [];
74+
for (var i = 0, len = array.length; i < len; i++) {
75+
var item = array[i];
76+
if (!contains(result, item)) result.push(item);
77+
}
78+
}
79+
return result;
80+
}
81+
7682
export function sum(array: any[], prop: string): number {
7783
var result = 0;
7884
for (var i = 0; i < array.length; i++) {

tests/baselines/reference/tupleTypes.errors.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616

1717
t = []; // Error
1818
~
19-
!!! Type '[]' is not assignable to type '[number, string]':
20-
!!! Property '0' is missing in type '[]'.
19+
!!! Type '{}[]' is not assignable to type '[number, string]':
20+
!!! Property '0' is missing in type '{}[]'.
2121
t = [1]; // Error
2222
~
2323
!!! Type '[number]' is not assignable to type '[number, string]':
@@ -53,7 +53,7 @@
5353
tt = [undefined, undefined];
5454
tt = []; // Error
5555
~~
56-
!!! Type '[]' is not assignable to type '[number, string]'.
56+
!!! Type '{}[]' is not assignable to type '[number, string]'.
5757

5858
var a: number[];
5959
var a1: [number, string];

0 commit comments

Comments
 (0)