diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5e037587de6c7..dccb7fdc84bca 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5,6 +5,11 @@ module ts { let nextNodeId = 1; let nextMergeId = 1; + interface SignatureIndexTypes { + [x: number]: IndexType + } + // TODO: LKG and replace [x: IndexKind] + // @internal export function getNodeId(node: Node): number { if (!node.id) node.id = nextNodeId++; @@ -54,7 +59,7 @@ module ts { getPropertiesOfType, getPropertyOfType, getSignaturesOfType, - getIndexTypeOfType, + getIndexTypeOfType: getIndexValueOfType, getReturnTypeOfSignature, getSymbolsInScope, getSymbolAtLocation, @@ -108,6 +113,7 @@ module ts { let globalArrayType: ObjectType; let globalStringType: ObjectType; let globalNumberType: ObjectType; + let globalNumberSubsetType: ObjectType; let globalBooleanType: ObjectType; let globalRegExpType: ObjectType; let globalTemplateStringsArrayType: ObjectType; @@ -1014,6 +1020,20 @@ module ts { return type; } + function cloneInterfaceType(type: InterfaceType, flags: TypeFlags): InterfaceType { + let cloneType = createType(type.flags); + cloneType.symbol = type.symbol; + cloneType.flags |= flags; + cloneType.baseTypes = type.baseTypes; + cloneType.declaredCallSignatures = type.declaredCallSignatures; + cloneType.declaredConstructSignatures = type.declaredCallSignatures; + cloneType.declaredNumberIndex = type.declaredNumberIndex; + cloneType.declaredStringIndex = type.declaredStringIndex; + cloneType.declaredProperties = type.declaredProperties; + cloneType.typeParameters = type.typeParameters; + return cloneType; + } + // A reserved member name starts with two underscores, but the third character cannot be an underscore // or the @ symbol. A third underscore indicates an escaped form of an identifer that started // with at least two underscores. The @ character indicates that the name is denoted by a well known ES @@ -1041,19 +1061,19 @@ module ts { return result || emptyArray; } - function setObjectTypeMembers(type: ObjectType, members: SymbolTable, callSignatures: Signature[], constructSignatures: Signature[], stringIndexType: Type, numberIndexType: Type): ResolvedType { + function setObjectTypeMembers(type: ObjectType, members: SymbolTable, callSignatures: Signature[], constructSignatures: Signature[], stringIndex: IndexType, numberIndex: IndexType): ResolvedType { (type).members = members; (type).properties = getNamedMembers(members); (type).callSignatures = callSignatures; (type).constructSignatures = constructSignatures; - if (stringIndexType) (type).stringIndexType = stringIndexType; - if (numberIndexType) (type).numberIndexType = numberIndexType; + if (stringIndex) (type).stringIndex = stringIndex; + if (numberIndex) (type).numberIndex = numberIndex; return type; } - function createAnonymousType(symbol: Symbol, members: SymbolTable, callSignatures: Signature[], constructSignatures: Signature[], stringIndexType: Type, numberIndexType: Type): ResolvedType { + function createAnonymousType(symbol: Symbol, members: SymbolTable, callSignatures: Signature[], constructSignatures: Signature[], stringIndex: IndexType, numberIndex: IndexType): ResolvedType { return setObjectTypeMembers(createObjectType(TypeFlags.Anonymous, symbol), - members, callSignatures, constructSignatures, stringIndexType, numberIndexType); + members, callSignatures, constructSignatures, stringIndex, numberIndex); } function forEachSymbolTableInScope(enclosingDeclaration: Node, callback: (symbolTable: SymbolTable) => T): T { @@ -1352,6 +1372,11 @@ module ts { return result; } + function indexTypeToString(type: IndexType, kind: IndexKind): string { + let index = type.typeOfIndex || (kind === IndexKind.String) ? stringType : numberType; + return '[' + typeToString(index) + ']: ' + typeToString(type.typeOfValue); + } + function getTypeAliasForTypeLiteral(type: Type): Symbol { if (type.symbol && type.symbol.flags & SymbolFlags.TypeLiteral) { let node = type.symbol.declarations[0].parent; @@ -1614,7 +1639,7 @@ module ts { function writeLiteralType(type: ObjectType, flags: TypeFormatFlags) { let resolved = resolveObjectOrUnionTypeMembers(type); - if (!resolved.properties.length && !resolved.stringIndexType && !resolved.numberIndexType) { + if (!resolved.properties.length && !resolved.stringIndex && !resolved.numberIndex) { if (!resolved.callSignatures.length && !resolved.constructSignatures.length) { writePunctuation(writer, SyntaxKind.OpenBraceToken); writePunctuation(writer, SyntaxKind.CloseBraceToken); @@ -1661,34 +1686,33 @@ module ts { writePunctuation(writer, SyntaxKind.SemicolonToken); writer.writeLine(); } - if (resolved.stringIndexType) { - // [x: string]: - writePunctuation(writer, SyntaxKind.OpenBracketToken); - writer.writeParameter(getIndexerParameterName(resolved, IndexKind.String, /*fallbackName*/"x")); - writePunctuation(writer, SyntaxKind.ColonToken); - writeSpace(writer); - writeKeyword(writer, SyntaxKind.StringKeyword); - writePunctuation(writer, SyntaxKind.CloseBracketToken); - writePunctuation(writer, SyntaxKind.ColonToken); - writeSpace(writer); - writeType(resolved.stringIndexType, TypeFormatFlags.None); - writePunctuation(writer, SyntaxKind.SemicolonToken); - writer.writeLine(); - } - if (resolved.numberIndexType) { - // [x: number]: + function writeIndexType(indexType: IndexType, kind: IndexKind) { + if (!indexType) { + return; + } writePunctuation(writer, SyntaxKind.OpenBracketToken); - writer.writeParameter(getIndexerParameterName(resolved, IndexKind.Number, /*fallbackName*/"x")); + writer.writeParameter(getIndexerParameterName(resolved, kind, /*fallbackName*/"x")); writePunctuation(writer, SyntaxKind.ColonToken); writeSpace(writer); - writeKeyword(writer, SyntaxKind.NumberKeyword); + + if (indexType.typeOfIndex && (indexType.typeOfIndex.flags & TypeFlags.Enum)) { + writeType(indexType.typeOfIndex, TypeFormatFlags.None); + writer.writeStringLiteral(kind === IndexKind.String ? "" : ""); + } + else { + writeKeyword(writer, kind === IndexKind.String ? SyntaxKind.StringKeyword : SyntaxKind.NumberKeyword); + } + writePunctuation(writer, SyntaxKind.CloseBracketToken); writePunctuation(writer, SyntaxKind.ColonToken); writeSpace(writer); - writeType(resolved.numberIndexType, TypeFormatFlags.None); + writeType(indexType.typeOfValue, TypeFormatFlags.None); writePunctuation(writer, SyntaxKind.SemicolonToken); writer.writeLine(); } + writeIndexType(resolved.stringIndex, IndexKind.String) + writeIndexType(resolved.numberIndex, IndexKind.Number) + for (let p of resolved.properties) { let t = getTypeOfSymbol(p); if (p.flags & (SymbolFlags.Function | SymbolFlags.Method) && !getPropertiesOfObjectType(t).length) { @@ -2070,8 +2094,8 @@ module ts { // Use type of the specified property, or otherwise, for a numeric name, the type of the numeric index signature, // or otherwise the type of the string index signature. type = getTypeOfPropertyOfType(parentType, name.text) || - isNumericLiteralName(name.text) && getIndexTypeOfType(parentType, IndexKind.Number) || - getIndexTypeOfType(parentType, IndexKind.String); + isNumericLiteralName(name.text) && getIndexValueOfType(parentType, IndexKind.Number) || + getIndexValueOfType(parentType, IndexKind.String); if (!type) { error(name, Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(parentType), declarationNameToString(name)); return unknownType; @@ -2514,8 +2538,11 @@ module ts { type.declaredProperties = getNamedMembers(symbol.members); type.declaredCallSignatures = emptyArray; type.declaredConstructSignatures = emptyArray; - type.declaredStringIndexType = getIndexTypeOfSymbol(symbol, IndexKind.String); - type.declaredNumberIndexType = getIndexTypeOfSymbol(symbol, IndexKind.Number); + + let indexTypes = getDeclaredIndexTypesOfSymbol(symbol); + + type.declaredStringIndex = indexTypes[IndexKind.String]; + type.declaredNumberIndex = indexTypes[IndexKind.Number]; } return links.declaredType; } @@ -2558,8 +2585,11 @@ module ts { type.declaredProperties = getNamedMembers(symbol.members); type.declaredCallSignatures = getSignaturesOfSymbol(symbol.members["__call"]); type.declaredConstructSignatures = getSignaturesOfSymbol(symbol.members["__new"]); - type.declaredStringIndexType = getIndexTypeOfSymbol(symbol, IndexKind.String); - type.declaredNumberIndexType = getIndexTypeOfSymbol(symbol, IndexKind.Number); + + let indexTypes = getDeclaredIndexTypesOfSymbol(symbol) + + type.declaredStringIndex = indexTypes[IndexKind.String]; + type.declaredNumberIndex = indexTypes[IndexKind.Number]; } return links.declaredType; } @@ -2585,7 +2615,7 @@ module ts { function getDeclaredTypeOfEnum(symbol: Symbol): Type { let links = getSymbolLinks(symbol); if (!links.declaredType) { - let type = createType(TypeFlags.Enum); + let type = createType(TypeFlags.Enum | TypeFlags.Subset); type.symbol = symbol; links.declaredType = type; } @@ -2672,19 +2702,21 @@ module ts { let members = type.symbol.members; let callSignatures = type.declaredCallSignatures; let constructSignatures = type.declaredConstructSignatures; - let stringIndexType = type.declaredStringIndexType; - let numberIndexType = type.declaredNumberIndexType; - if (type.baseTypes.length) { + let stringIndex = type.declaredStringIndex + let numberIndex = type.declaredNumberIndex + + if (type.baseTypes && type.baseTypes.length) { members = createSymbolTable(type.declaredProperties); forEach(type.baseTypes, baseType => { addInheritedMembers(members, getPropertiesOfObjectType(baseType)); callSignatures = concatenate(callSignatures, getSignaturesOfType(baseType, SignatureKind.Call)); constructSignatures = concatenate(constructSignatures, getSignaturesOfType(baseType, SignatureKind.Construct)); - stringIndexType = stringIndexType || getIndexTypeOfType(baseType, IndexKind.String); - numberIndexType = numberIndexType || getIndexTypeOfType(baseType, IndexKind.Number); + stringIndex = stringIndex || getIndexOfType(baseType, IndexKind.String, /* inherited */ true); + numberIndex = numberIndex || getIndexOfType(baseType, IndexKind.Number, /* inherited */ true); }); } - setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexType, numberIndexType); + + setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndex, numberIndex); } function resolveTypeReferenceMembers(type: TypeReference): void { @@ -2693,17 +2725,18 @@ module ts { let members = createInstantiatedSymbolTable(target.declaredProperties, mapper); let callSignatures = instantiateList(target.declaredCallSignatures, mapper, instantiateSignature); let constructSignatures = instantiateList(target.declaredConstructSignatures, mapper, instantiateSignature); - let stringIndexType = target.declaredStringIndexType ? instantiateType(target.declaredStringIndexType, mapper) : undefined; - let numberIndexType = target.declaredNumberIndexType ? instantiateType(target.declaredNumberIndexType, mapper) : undefined; + + let stringIndex = target.declaredStringIndex ? { typeOfValue: instantiateType(target.declaredStringIndex.typeOfValue, mapper) } : undefined; + let numberIndex = target.declaredNumberIndex ? { typeOfValue: instantiateType(target.declaredNumberIndex.typeOfValue, mapper) } : undefined; forEach(target.baseTypes, baseType => { let instantiatedBaseType = instantiateType(baseType, mapper); addInheritedMembers(members, getPropertiesOfObjectType(instantiatedBaseType)); callSignatures = concatenate(callSignatures, getSignaturesOfType(instantiatedBaseType, SignatureKind.Call)); constructSignatures = concatenate(constructSignatures, getSignaturesOfType(instantiatedBaseType, SignatureKind.Construct)); - stringIndexType = stringIndexType || getIndexTypeOfType(instantiatedBaseType, IndexKind.String); - numberIndexType = numberIndexType || getIndexTypeOfType(instantiatedBaseType, IndexKind.Number); + stringIndex = stringIndex || getIndexOfType(instantiatedBaseType, IndexKind.String); + numberIndex = numberIndex || getIndexOfType(instantiatedBaseType, IndexKind.Number); }); - setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexType, numberIndexType); + setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndex, numberIndex); } function createSignature(declaration: SignatureDeclaration, typeParameters: TypeParameter[], parameters: Symbol[], @@ -2753,7 +2786,7 @@ module ts { let arrayType = resolveObjectOrUnionTypeMembers(createArrayType(getUnionType(type.elementTypes))); let members = createTupleTypeMemberSymbols(type.elementTypes); addInheritedMembers(members, arrayType.properties); - setObjectTypeMembers(type, members, arrayType.callSignatures, arrayType.constructSignatures, arrayType.stringIndexType, arrayType.numberIndexType); + setObjectTypeMembers(type, members, arrayType.callSignatures, arrayType.constructSignatures, arrayType.stringIndex, arrayType.numberIndex); } function signatureListsIdentical(s: Signature[], t: Signature[]): boolean { @@ -2797,7 +2830,7 @@ module ts { function getUnionIndexType(types: Type[], kind: IndexKind): Type { let indexTypes: Type[] = []; for (let type of types) { - let indexType = getIndexTypeOfType(type, kind); + let indexType = getIndexValueOfType(type, kind); if (!indexType) { return undefined; } @@ -2813,7 +2846,7 @@ module ts { let constructSignatures = getUnionSignatures(type.types, SignatureKind.Construct); let stringIndexType = getUnionIndexType(type.types, IndexKind.String); let numberIndexType = getUnionIndexType(type.types, IndexKind.Number); - setObjectTypeMembers(type, emptySymbols, callSignatures, constructSignatures, stringIndexType, numberIndexType); + setObjectTypeMembers(type, emptySymbols, callSignatures, constructSignatures, stringIndexType ? { typeOfValue: stringIndexType } : undefined, numberIndexType ? { typeOfValue: numberIndexType }: undefined); } function resolveAnonymousTypeMembers(type: ObjectType) { @@ -2821,15 +2854,15 @@ module ts { let members: SymbolTable; let callSignatures: Signature[]; let constructSignatures: Signature[]; - let stringIndexType: Type; - let numberIndexType: Type; + let stringIndex: IndexType; + let numberIndex: IndexType; if (symbol.flags & SymbolFlags.TypeLiteral) { members = symbol.members; callSignatures = getSignaturesOfSymbol(members["__call"]); constructSignatures = getSignaturesOfSymbol(members["__new"]); - stringIndexType = getIndexTypeOfSymbol(symbol, IndexKind.String); - numberIndexType = getIndexTypeOfSymbol(symbol, IndexKind.Number); + stringIndex = getIndexTypeOfSymbol(symbol, IndexKind.String); + numberIndex = getIndexTypeOfSymbol(symbol, IndexKind.Number); } else { // Combinations of function, class, enum and module @@ -2853,13 +2886,14 @@ module ts { addInheritedMembers(members, getPropertiesOfObjectType(getTypeOfSymbol(classType.baseTypes[0].symbol))); } } - stringIndexType = undefined; - numberIndexType = (symbol.flags & SymbolFlags.Enum) ? stringType : undefined; + stringIndex = undefined; + numberIndex = (symbol.flags & SymbolFlags.Enum) ? { typeOfIndex: type, typeOfValue: stringType } : undefined; } - setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexType, numberIndexType); + setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndex, numberIndex); } function resolveObjectOrUnionTypeMembers(type: ObjectType): ResolvedType { + //console.log(type) if (!(type).members) { if (type.flags & (TypeFlags.Class | TypeFlags.Interface)) { resolveClassOrInterfaceMembers(type); @@ -2936,7 +2970,11 @@ module ts { type = globalStringType; } else if (type.flags & TypeFlags.NumberLike) { - type = globalNumberType; + if (type.flags & TypeFlags.Subset) { + type = globalNumberSubsetType; + } else { + type = globalNumberType; + } } else if (type.flags & TypeFlags.Boolean) { type = globalBooleanType; @@ -3043,17 +3081,37 @@ module ts { return false; } - function getIndexTypeOfObjectOrUnionType(type: Type, kind: IndexKind): Type { + function resolveObjectOrUnionType(type: Type): ResolvedType { + if (type.flags & (TypeFlags.ObjectType | TypeFlags.Union)) { + return resolveObjectOrUnionTypeMembers(type); + } + } + + function getIndexTypeOfObjectOrUnionType(type: Type, kind: IndexKind): IndexType { if (type.flags & (TypeFlags.ObjectType | TypeFlags.Union)) { let resolved = resolveObjectOrUnionTypeMembers(type); - return kind === IndexKind.String ? resolved.stringIndexType : resolved.numberIndexType; + return kind === IndexKind.String ? resolved.stringIndex : resolved.numberIndex; } } + function getIndexValueOfObjectOrUnionType(type: Type, kind: IndexKind): Type { + let indexType = getIndexTypeOfObjectOrUnionType(type, kind); + return indexType ? indexType.typeOfValue : undefined + } + // Return the index type of the given kind in the given type. Creates synthetic union index types when necessary and // maps primitive types and type parameters are to their apparent types. - function getIndexTypeOfType(type: Type, kind: IndexKind): Type { - return getIndexTypeOfObjectOrUnionType(getApparentType(type), kind); + function getIndexOfType(type: Type, kind: IndexKind, inherited = false): IndexType { + let indexType = getIndexTypeOfObjectOrUnionType(getApparentType(type), kind); + if (indexType && inherited) { + indexType.inherited = inherited; + } + return indexType; + } + + function getIndexValueOfType(type: Type, kind: IndexKind): Type { + let indexType = getIndexOfType(type, kind); + return indexType ? indexType.typeOfValue : undefined } // Return list of type parameters with duplicates removed (duplicate identifier errors are generated in the actual @@ -3265,11 +3323,38 @@ module ts { return undefined; } - function getIndexTypeOfSymbol(symbol: Symbol, kind: IndexKind): Type { - let declaration = getIndexDeclarationOfSymbol(symbol, kind); - return declaration - ? declaration.type ? getTypeFromTypeNodeOrHeritageClauseElement(declaration.type) : anyType - : undefined; + function getDeclaredIndexTypesOfSymbol(symbol: Symbol): SignatureIndexTypes { + let indexTypes: SignatureIndexTypes = {} + let indexSymbol = getIndexSymbol(symbol); + if (indexSymbol) { + for (let decl of indexSymbol.declarations) { + if (decl.parameters.length === 1) { + let type = getTypeFromIndexSignatureParameter(decl.parameters[0]); + if (!type) { + continue; + } + let kind = (type.flags & TypeFlags.NumberLike) ? IndexKind.Number : (type.flags & TypeFlags.String) ? IndexKind.String: null; + if(kind !== null) { + indexTypes[kind] = { + typeOfIndex: type, + typeOfValue: decl.type ? getTypeFromTypeNodeOrHeritageClauseElement(decl.type) : anyType, + declaredNode: decl + } + } + } + } + } + return indexTypes; + } + + function getIndexTypeOfSymbol(symbol: Symbol, kind: IndexKind): IndexType { + let indexTypes = getDeclaredIndexTypesOfSymbol(symbol); + return indexTypes[kind]; + } + + function getIndexValueOfSymbol(symbol: Symbol, kind: IndexKind): Type { + let info = getIndexTypeOfSymbol(symbol, kind); + return info ? info.typeOfValue : undefined } function getConstraintOfTypeParameter(type: TypeParameter): Type { @@ -3834,13 +3919,17 @@ module ts { result.members = createSymbolTable(result.properties); result.callSignatures = instantiateList(getSignaturesOfType(type, SignatureKind.Call), mapper, instantiateSignature); result.constructSignatures = instantiateList(getSignaturesOfType(type, SignatureKind.Construct), mapper, instantiateSignature); - let stringIndexType = getIndexTypeOfType(type, IndexKind.String); - let numberIndexType = getIndexTypeOfType(type, IndexKind.Number); - if (stringIndexType) result.stringIndexType = instantiateType(stringIndexType, mapper); - if (numberIndexType) result.numberIndexType = instantiateType(numberIndexType, mapper); + let stringIndex = getIndexOfType(type, IndexKind.String); + let numberIndex = getIndexOfType(type, IndexKind.Number); + if (stringIndex) result.stringIndex = instantiateIndexType(stringIndex, mapper); + if (numberIndex) result.numberIndex = instantiateIndexType(numberIndex, mapper); return result; } + function instantiateIndexType(typeIndex: IndexType, mapper: TypeMapper): IndexType { + return { typeOfValue: instantiateType(typeIndex.typeOfValue, mapper), typeOfIndex: typeIndex.typeOfIndex } + } + function instantiateType(type: Type, mapper: TypeMapper): Type { if (mapper !== identityMapper) { if (type.flags & TypeFlags.TypeParameter) { @@ -3938,7 +4027,7 @@ module ts { return checkTypeRelatedTo(source, target, subtypeRelation, errorNode, headMessage, containingMessageChain); } - function checkTypeAssignableTo(source: Type, target: Type, errorNode: Node, headMessage?: DiagnosticMessage): boolean { + function checkTypeAssignableTo(source: Type, target: Type, errorNode: Node, headMessage?: DiagnosticMessage): boolean{ return checkTypeRelatedTo(source, target, assignableRelation, errorNode, headMessage); } @@ -4010,6 +4099,7 @@ module ts { if (relation === assignableRelation) { if (source.flags & TypeFlags.Any) return Ternary.True; if (source === numberType && target.flags & TypeFlags.Enum) return Ternary.True; + //if (source.symbol && source.symbol === target.symbol && target.flags & TypeFlags.Subset) return Ternary.True; } } if (source.flags & TypeFlags.Union || target.flags & TypeFlags.Union) { @@ -4469,9 +4559,10 @@ module ts { if (relation === identityRelation) { return indexTypesIdenticalTo(IndexKind.String, source, target); } - let targetType = getIndexTypeOfType(target, IndexKind.String); + // TODO: string > number > number.subset + let targetType = getIndexValueOfType(target, IndexKind.String); if (targetType) { - let sourceType = getIndexTypeOfType(source, IndexKind.String); + let sourceType = getIndexValueOfType(source, IndexKind.String); if (!sourceType) { if (reportErrors) { reportError(Diagnostics.Index_signature_is_missing_in_type_0, typeToString(source)); @@ -4494,10 +4585,10 @@ module ts { if (relation === identityRelation) { return indexTypesIdenticalTo(IndexKind.Number, source, target); } - let targetType = getIndexTypeOfType(target, IndexKind.Number); + let targetType = getIndexValueOfType(target, IndexKind.Number); if (targetType) { - let sourceStringType = getIndexTypeOfType(source, IndexKind.String); - let sourceNumberType = getIndexTypeOfType(source, IndexKind.Number); + let sourceStringType = getIndexValueOfType(source, IndexKind.String); + let sourceNumberType = getIndexValueOfType(source, IndexKind.Number); if (!(sourceStringType || sourceNumberType)) { if (reportErrors) { reportError(Diagnostics.Index_signature_is_missing_in_type_0, typeToString(source)); @@ -4524,8 +4615,8 @@ module ts { } function indexTypesIdenticalTo(indexKind: IndexKind, source: ObjectType, target: ObjectType): Ternary { - let targetType = getIndexTypeOfType(target, indexKind); - let sourceType = getIndexTypeOfType(source, indexKind); + let targetType = getIndexValueOfType(target, indexKind); + let sourceType = getIndexValueOfType(source, indexKind); if (!sourceType && !targetType) { return Ternary.True; } @@ -4699,11 +4790,11 @@ module ts { } members[p.name] = p; }); - let stringIndexType = getIndexTypeOfType(type, IndexKind.String); - let numberIndexType = getIndexTypeOfType(type, IndexKind.Number); - if (stringIndexType) stringIndexType = getWidenedType(stringIndexType); - if (numberIndexType) numberIndexType = getWidenedType(numberIndexType); - return createAnonymousType(type.symbol, members, emptyArray, emptyArray, stringIndexType, numberIndexType); + let stringIndex = getIndexOfType(type, IndexKind.String); + let numberIndex = getIndexOfType(type, IndexKind.Number); + if (stringIndex) stringIndex = {typeOfValue: getWidenedType(stringIndex.typeOfValue) }; + if (numberIndex) numberIndex = {typeOfValue: getWidenedType(numberIndex.typeOfValue) }; + return createAnonymousType(type.symbol, members, emptyArray, emptyArray, stringIndex, numberIndex); } function getWidenedType(type: Type): Type { @@ -4978,9 +5069,9 @@ module ts { } function inferFromIndexTypes(source: Type, target: Type, sourceKind: IndexKind, targetKind: IndexKind) { - let targetIndexType = getIndexTypeOfType(target, targetKind); + let targetIndexType = getIndexValueOfType(target, targetKind); if (targetIndexType) { - let sourceIndexType = getIndexTypeOfType(source, sourceKind); + let sourceIndexType = getIndexValueOfType(source, sourceKind); if (sourceIndexType) { inferFromTypes(sourceIndexType, targetIndexType); } @@ -5792,7 +5883,7 @@ module ts { } function getIndexTypeOfContextualType(type: Type, kind: IndexKind) { - return applyToContextualType(type, t => getIndexTypeOfObjectOrUnionType(t, kind)); + return applyToContextualType(type, t => getIndexValueOfObjectOrUnionType(t, kind)); } // Return true if the given contextual type is a tuple-like type @@ -5802,7 +5893,7 @@ module ts { // Return true if the given contextual type provides an index signature of the given kind function contextualTypeHasIndexSignature(type: Type, kind: IndexKind): boolean { - return !!(type.flags & TypeFlags.Union ? forEach((type).types, t => getIndexTypeOfObjectOrUnionType(t, kind)) : getIndexTypeOfObjectOrUnionType(type, kind)); + return !!(type.flags & TypeFlags.Union ? forEach((type).types, t => getIndexValueOfObjectOrUnionType(t, kind)) : getIndexValueOfObjectOrUnionType(type, kind)); } // In an object literal contextually typed by a type T, the contextual type of a property assignment is the type of @@ -6145,7 +6236,7 @@ module ts { let stringIndexType = getIndexType(IndexKind.String); let numberIndexType = getIndexType(IndexKind.Number); - let result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, stringIndexType, numberIndexType); + let result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, stringIndexType ? { typeOfValue: stringIndexType } : undefined, numberIndexType ? { typeOfValue: numberIndexType } : undefined); result.flags |= TypeFlags.ObjectLiteral | TypeFlags.ContainsObjectLiteral | (typeFlags & TypeFlags.ContainsUndefinedOrNull); return result; @@ -6349,14 +6440,14 @@ module ts { // Try to use a number indexer. if (allConstituentTypesHaveKind(indexType, TypeFlags.Any | TypeFlags.NumberLike)) { - let numberIndexType = getIndexTypeOfType(objectType, IndexKind.Number); + let numberIndexType = getIndexValueOfType(objectType, IndexKind.Number); if (numberIndexType) { return numberIndexType; } } // Try to use string indexing. - let stringIndexType = getIndexTypeOfType(objectType, IndexKind.String); + let stringIndexType = getIndexValueOfType(objectType, IndexKind.String); if (stringIndexType) { return stringIndexType; } @@ -6600,7 +6691,7 @@ module ts { if (type.flags & TypeFlags.ObjectType) { let resolved = resolveObjectOrUnionTypeMembers(type); if (resolved.callSignatures.length === 1 && resolved.constructSignatures.length === 0 && - resolved.properties.length === 0 && !resolved.stringIndexType && !resolved.numberIndexType) { + resolved.properties.length === 0 && !resolved.stringIndex && !resolved.numberIndex) { return resolved.callSignatures[0]; } } @@ -7599,8 +7690,8 @@ module ts { let name = (p).name; let type = sourceType.flags & TypeFlags.Any ? sourceType : getTypeOfPropertyOfType(sourceType, name.text) || - isNumericLiteralName(name.text) && getIndexTypeOfType(sourceType, IndexKind.Number) || - getIndexTypeOfType(sourceType, IndexKind.String); + isNumericLiteralName(name.text) && getIndexValueOfType(sourceType, IndexKind.Number) || + getIndexValueOfType(sourceType, IndexKind.String); if (type) { checkDestructuringAssignment((p).initializer || name, type); } @@ -9417,7 +9508,7 @@ module ts { } if (isArrayLikeType(inputType)) { - return getIndexTypeOfType(inputType, IndexKind.Number); + return getIndexValueOfType(inputType, IndexKind.Number); } error(errorNode, Diagnostics.Type_0_is_not_an_array_type, typeToString(inputType)); @@ -9576,7 +9667,7 @@ module ts { return hasStringConstituent ? stringType : unknownType; } - let arrayElementType = getIndexTypeOfType(arrayType, IndexKind.Number) || unknownType; + let arrayElementType = getIndexValueOfType(arrayType, IndexKind.Number) || unknownType; if (hasStringConstituent) { // This is just an optimization for the case where arrayOrStringType is string | string[] if (arrayElementType.flags & TypeFlags.StringLike) { @@ -9757,17 +9848,22 @@ module ts { } function checkIndexConstraints(type: Type) { - let declaredNumberIndexer = getIndexDeclarationOfSymbol(type.symbol, IndexKind.Number); - let declaredStringIndexer = getIndexDeclarationOfSymbol(type.symbol, IndexKind.String); - let stringIndexType = getIndexTypeOfType(type, IndexKind.String); - let numberIndexType = getIndexTypeOfType(type, IndexKind.Number); + let resolved = resolveObjectOrUnionType(type); + if (!resolved) { + return; + } + + let stringIndex = resolved.stringIndex || {typeOfValue: undefined}; + let numberIndex = resolved.numberIndex || {typeOfValue: undefined}; + let alphaNumeric = (stringIndex.typeOfValue && numberIndex.typeOfValue) ? true : false; + + if (stringIndex.typeOfValue || numberIndex.typeOfValue) { - if (stringIndexType || numberIndexType) { forEach(getPropertiesOfObjectType(type), prop => { let propType = getTypeOfSymbol(prop); - checkIndexConstraintForProperty(prop, propType, type, declaredStringIndexer, stringIndexType, IndexKind.String); - checkIndexConstraintForProperty(prop, propType, type, declaredNumberIndexer, numberIndexType, IndexKind.Number); + checkIndexConstraintForProperty(prop, propType, type, stringIndex, IndexKind.String, alphaNumeric); + checkIndexConstraintForProperty(prop, propType, type, numberIndex, IndexKind.Number, alphaNumeric); }); if (type.flags & TypeFlags.Class && type.symbol.valueDeclaration.kind === SyntaxKind.ClassDeclaration) { @@ -9778,37 +9874,41 @@ module ts { // and properties with literal names were already checked. if (!(member.flags & NodeFlags.Static) && hasDynamicName(member)) { let propType = getTypeOfSymbol(member.symbol); - checkIndexConstraintForProperty(member.symbol, propType, type, declaredStringIndexer, stringIndexType, IndexKind.String); - checkIndexConstraintForProperty(member.symbol, propType, type, declaredNumberIndexer, numberIndexType, IndexKind.Number); + checkIndexConstraintForProperty(member.symbol, propType, type, stringIndex, IndexKind.String, alphaNumeric); + checkIndexConstraintForProperty(member.symbol, propType, type, numberIndex, IndexKind.Number, alphaNumeric); } } } } let errorNode: Node; - if (stringIndexType && numberIndexType) { - errorNode = declaredNumberIndexer || declaredStringIndexer; - // condition 'errorNode === undefined' may appear if types does not declare nor string neither number indexer - if (!errorNode && (type.flags & TypeFlags.Interface)) { - let someBaseTypeHasBothIndexers = forEach((type).baseTypes, base => getIndexTypeOfType(base, IndexKind.String) && getIndexTypeOfType(base, IndexKind.Number)); - errorNode = someBaseTypeHasBothIndexers ? undefined : type.symbol.declarations[0]; + if (alphaNumeric) { + let possibleNodes = [numberIndex, stringIndex]; + for (let typeIndex of possibleNodes) { + if (typeIndex.declaredNode) { + errorNode = typeIndex.declaredNode; + if (!typeIndex.inherited) { + // TODO: should preserve ordering so first declared node is used + break; + } + } } } - if (errorNode && !isTypeAssignableTo(numberIndexType, stringIndexType)) { + if (errorNode && !isTypeAssignableTo(numberIndex.typeOfValue, stringIndex.typeOfValue)) { error(errorNode, Diagnostics.Numeric_index_type_0_is_not_assignable_to_string_index_type_1, - typeToString(numberIndexType), typeToString(stringIndexType)); + indexTypeToString(numberIndex, IndexKind.Number), indexTypeToString(stringIndex, IndexKind.String)); } function checkIndexConstraintForProperty( prop: Symbol, propertyType: Type, containingType: Type, - indexDeclaration: Declaration, - indexType: Type, - indexKind: IndexKind): void { + indexType: IndexType, + indexKind: IndexKind, + alphaNumeric: boolean): void { - if (!indexType) { + if (!indexType.typeOfValue) { return; } @@ -9823,24 +9923,26 @@ module ts { if (prop.valueDeclaration.name.kind === SyntaxKind.ComputedPropertyName || prop.parent === containingType.symbol) { errorNode = prop.valueDeclaration; } - else if (indexDeclaration) { - errorNode = indexDeclaration; + else if (indexType.declaredNode) { + if (!alphaNumeric) { + errorNode = indexType.declaredNode; + } } else if (containingType.flags & TypeFlags.Interface) { // for interfaces property and indexer might be inherited from different bases // check if any base class already has both property and indexer. // check should be performed only if 'type' is the first type that brings property\indexer together - let someBaseClassHasBothPropertyAndIndexer = forEach((containingType).baseTypes, base => getPropertyOfObjectType(base, prop.name) && getIndexTypeOfType(base, indexKind)); + let someBaseClassHasBothPropertyAndIndexer = forEach((containingType).baseTypes, base => getPropertyOfObjectType(base, prop.name) && getIndexValueOfType(base, indexKind)); errorNode = someBaseClassHasBothPropertyAndIndexer ? undefined : containingType.symbol.declarations[0]; } - - if (errorNode && !isTypeAssignableTo(propertyType, indexType)) { + if (errorNode && !isTypeAssignableTo(propertyType, indexType.typeOfValue)) { let errorMessage = indexKind === IndexKind.String ? Diagnostics.Property_0_of_type_1_is_not_assignable_to_string_index_type_2 : Diagnostics.Property_0_of_type_1_is_not_assignable_to_numeric_index_type_2; - error(errorNode, errorMessage, symbolToString(prop), typeToString(propertyType), typeToString(indexType)); + error(errorNode, errorMessage, symbolToString(prop), typeToString(propertyType), typeToString(indexType.typeOfValue)); } + // TODO: indexTypeToString() Diagnostics.Property_0_of_type_1_is_not_assignable_to_index_type_2 } } @@ -11886,7 +11988,10 @@ module ts { globalObjectType = getGlobalType("Object"); globalFunctionType = getGlobalType("Function"); globalStringType = getGlobalType("String"); + //globalStringSubsetType = cloneObjectType(globalStringType, TypeFlags.Subset); globalNumberType = getGlobalType("Number"); + globalNumberSubsetType = cloneInterfaceType(globalNumberType, TypeFlags.Subset); + globalBooleanType = getGlobalType("Boolean"); globalRegExpType = getGlobalType("RegExp"); globalTypedPropertyDescriptorType = getTypeOfGlobalSymbol(getGlobalTypeSymbol("TypedPropertyDescriptor"), 1); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 7477705796396..b48e93dd1c30c 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1423,11 +1423,13 @@ module ts { ContainsUndefinedOrNull = 0x00040000, // Type is or contains Undefined or Null type ContainsObjectLiteral = 0x00080000, // Type is or contains object literal type ESSymbol = 0x00100000, // Type of symbol primitive introduced in ES6 + Subset = 0x00200000, // Type that has a subset of valid values Intrinsic = Any | String | Number | Boolean | ESSymbol | Void | Undefined | Null, Primitive = String | Number | Boolean | ESSymbol | Void | Undefined | Null | StringLiteral | Enum, StringLike = String | StringLiteral, NumberLike = Number | Enum, + SubsetMaybe = Enum | Reference, ObjectType = Class | Interface | Reference | Tuple | Anonymous, RequiresWidening = ContainsUndefinedOrNull | ContainsObjectLiteral } @@ -1459,8 +1461,8 @@ module ts { declaredProperties: Symbol[]; // Declared members declaredCallSignatures: Signature[]; // Declared call signatures declaredConstructSignatures: Signature[]; // Declared construct signatures - declaredStringIndexType: Type; // Declared string index type - declaredNumberIndexType: Type; // Declared numeric index type + declaredStringIndex: IndexType; // Declared string type + declaredNumberIndex: IndexType; // Declared numeric type } // Type references (TypeFlags.Reference) @@ -1484,14 +1486,21 @@ module ts { resolvedProperties: SymbolTable; // Cache of resolved properties } + export interface IndexType { + typeOfIndex?: Type // string|number|enum + typeOfValue: Type + declaredNode?: Declaration + inherited?: boolean + } + // Resolved object or union type export interface ResolvedType extends ObjectType, UnionType { members: SymbolTable; // Properties by name properties: Symbol[]; // Properties callSignatures: Signature[]; // Call signatures of type constructSignatures: Signature[]; // Construct signatures of type - stringIndexType: Type; // String index type - numberIndexType: Type; // Numeric index type + stringIndex: IndexType; // String index type + numberIndex: IndexType; // Number index type } // Type parameters (TypeFlags.TypeParameter) diff --git a/tests/baselines/reference/decoratorOnClassMethod11.js b/tests/baselines/reference/decoratorOnClassMethod11.js index 71d4298f02cbf..f8276de2fe3f7 100644 --- a/tests/baselines/reference/decoratorOnClassMethod11.js +++ b/tests/baselines/reference/decoratorOnClassMethod11.js @@ -1,11 +1,11 @@ //// [decoratorOnClassMethod11.ts] -module M { - class C { - decorator(target: Object, key: string): void { } - - @this.decorator - method() { } - } +module M { + class C { + decorator(target: Object, key: string): void { } + + @this.decorator + method() { } + } } //// [decoratorOnClassMethod11.js] diff --git a/tests/baselines/reference/enumAssignmentCompat.errors.txt b/tests/baselines/reference/enumAssignmentCompat.errors.txt index 3cddaf459666c..86308cdd3ea6d 100644 --- a/tests/baselines/reference/enumAssignmentCompat.errors.txt +++ b/tests/baselines/reference/enumAssignmentCompat.errors.txt @@ -2,9 +2,11 @@ tests/cases/compiler/enumAssignmentCompat.ts(26,5): error TS2322: Type 'typeof W tests/cases/compiler/enumAssignmentCompat.ts(28,5): error TS2322: Type 'W' is not assignable to type 'typeof W'. Property 'D' is missing in type 'Number'. tests/cases/compiler/enumAssignmentCompat.ts(30,5): error TS2322: Type 'number' is not assignable to type 'typeof W'. + Property 'D' is missing in type 'Number'. tests/cases/compiler/enumAssignmentCompat.ts(32,5): error TS2322: Type 'W' is not assignable to type 'WStatic'. Property 'a' is missing in type 'Number'. tests/cases/compiler/enumAssignmentCompat.ts(33,5): error TS2322: Type 'number' is not assignable to type 'WStatic'. + Property 'a' is missing in type 'Number'. ==== tests/cases/compiler/enumAssignmentCompat.ts (5 errors) ==== @@ -45,6 +47,7 @@ tests/cases/compiler/enumAssignmentCompat.ts(33,5): error TS2322: Type 'number' var d: typeof W = 3; // error ~ !!! error TS2322: Type 'number' is not assignable to type 'typeof W'. +!!! error TS2322: Property 'D' is missing in type 'Number'. var e: typeof W.a = 4; var f: WStatic = W.a; // error ~ @@ -53,6 +56,7 @@ tests/cases/compiler/enumAssignmentCompat.ts(33,5): error TS2322: Type 'number' var g: WStatic = 5; // error ~ !!! error TS2322: Type 'number' is not assignable to type 'WStatic'. +!!! error TS2322: Property 'a' is missing in type 'Number'. var h: W = 3; var i: W = W.a; i = W.a; diff --git a/tests/baselines/reference/enumAssignmentCompat2.errors.txt b/tests/baselines/reference/enumAssignmentCompat2.errors.txt index d87d6acf6a099..be8ed9806a6db 100644 --- a/tests/baselines/reference/enumAssignmentCompat2.errors.txt +++ b/tests/baselines/reference/enumAssignmentCompat2.errors.txt @@ -2,9 +2,11 @@ tests/cases/compiler/enumAssignmentCompat2.ts(25,5): error TS2322: Type 'typeof tests/cases/compiler/enumAssignmentCompat2.ts(27,5): error TS2322: Type 'W' is not assignable to type 'typeof W'. Property 'a' is missing in type 'Number'. tests/cases/compiler/enumAssignmentCompat2.ts(29,5): error TS2322: Type 'number' is not assignable to type 'typeof W'. + Property 'a' is missing in type 'Number'. tests/cases/compiler/enumAssignmentCompat2.ts(31,5): error TS2322: Type 'W' is not assignable to type 'WStatic'. Property 'a' is missing in type 'Number'. tests/cases/compiler/enumAssignmentCompat2.ts(32,5): error TS2322: Type 'number' is not assignable to type 'WStatic'. + Property 'a' is missing in type 'Number'. ==== tests/cases/compiler/enumAssignmentCompat2.ts (5 errors) ==== @@ -44,6 +46,7 @@ tests/cases/compiler/enumAssignmentCompat2.ts(32,5): error TS2322: Type 'number' var d: typeof W = 3; // error ~ !!! error TS2322: Type 'number' is not assignable to type 'typeof W'. +!!! error TS2322: Property 'a' is missing in type 'Number'. var e: typeof W.a = 4; var f: WStatic = W.a; // error ~ @@ -52,6 +55,7 @@ tests/cases/compiler/enumAssignmentCompat2.ts(32,5): error TS2322: Type 'number' var g: WStatic = 5; // error ~ !!! error TS2322: Type 'number' is not assignable to type 'WStatic'. +!!! error TS2322: Property 'a' is missing in type 'Number'. var h: W = 3; var i: W = W.a; i = W.a; diff --git a/tests/baselines/reference/genericCallWithObjectTypeArgsAndIndexersErrors.errors.txt b/tests/baselines/reference/genericCallWithObjectTypeArgsAndIndexersErrors.errors.txt index 2a7bfd696cc15..d183e8b38e07e 100644 --- a/tests/baselines/reference/genericCallWithObjectTypeArgsAndIndexersErrors.errors.txt +++ b/tests/baselines/reference/genericCallWithObjectTypeArgsAndIndexersErrors.errors.txt @@ -1,5 +1,5 @@ tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithObjectTypeArgsAndIndexersErrors.ts(15,17): error TS2313: Constraint of a type parameter cannot reference any type parameter from the same type parameter list. -tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithObjectTypeArgsAndIndexersErrors.ts(18,9): error TS2413: Numeric index type 'T' is not assignable to string index type 'Object'. +tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithObjectTypeArgsAndIndexersErrors.ts(18,9): error TS2413: Numeric index type '[string]: T' is not assignable to string index type '[string]: Object'. tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithObjectTypeArgsAndIndexersErrors.ts(23,9): error TS2322: Type 'T' is not assignable to type 'U'. @@ -25,7 +25,7 @@ tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithObj [x: string]: Object; [x: number]: T; ~~~~~~~~~~~~~~~ -!!! error TS2413: Numeric index type 'T' is not assignable to string index type 'Object'. +!!! error TS2413: Numeric index type '[string]: T' is not assignable to string index type '[string]: Object'. }; var r2 = foo(b); var d = r2[1]; diff --git a/tests/baselines/reference/indexSignatureTypeCheck.errors.txt b/tests/baselines/reference/indexSignatureTypeCheck.errors.txt index 1931b5bd7dded..af377d4f27ced 100644 --- a/tests/baselines/reference/indexSignatureTypeCheck.errors.txt +++ b/tests/baselines/reference/indexSignatureTypeCheck.errors.txt @@ -7,15 +7,15 @@ tests/cases/compiler/indexSignatureTypeCheck.ts(50,5): error TS2375: Duplicate n tests/cases/compiler/indexSignatureTypeCheck.ts(55,5): error TS2375: Duplicate number index signature. tests/cases/compiler/indexSignatureTypeCheck.ts(65,1): error TS2322: Type '{ [x: number]: string; }' is not assignable to type '{ [x: string]: string; }'. Index signature is missing in type '{ [x: number]: string; }'. -tests/cases/compiler/indexSignatureTypeCheck.ts(66,1): error TS2322: Type '{ [x: number]: number; }' is not assignable to type '{ [x: string]: string; }'. - Index signature is missing in type '{ [x: number]: number; }'. -tests/cases/compiler/indexSignatureTypeCheck.ts(70,1): error TS2322: Type '{ [x: number]: number; }' is not assignable to type '{ [x: number]: string; }'. +tests/cases/compiler/indexSignatureTypeCheck.ts(66,1): error TS2322: Type '{ [x: E]: number; }' is not assignable to type '{ [x: string]: string; }'. + Index signature is missing in type '{ [x: E]: number; }'. +tests/cases/compiler/indexSignatureTypeCheck.ts(70,1): error TS2322: Type '{ [x: E]: number; }' is not assignable to type '{ [x: number]: string; }'. Index signatures are incompatible. Type 'number' is not assignable to type 'string'. -tests/cases/compiler/indexSignatureTypeCheck.ts(72,1): error TS2322: Type '{ [x: string]: string; }' is not assignable to type '{ [x: number]: number; }'. +tests/cases/compiler/indexSignatureTypeCheck.ts(72,1): error TS2322: Type '{ [x: string]: string; }' is not assignable to type '{ [x: E]: number; }'. Index signatures are incompatible. Type 'string' is not assignable to type 'number'. -tests/cases/compiler/indexSignatureTypeCheck.ts(73,1): error TS2322: Type '{ [x: number]: string; }' is not assignable to type '{ [x: number]: number; }'. +tests/cases/compiler/indexSignatureTypeCheck.ts(73,1): error TS2322: Type '{ [x: number]: string; }' is not assignable to type '{ [x: E]: number; }'. Index signatures are incompatible. Type 'string' is not assignable to type 'number'. @@ -105,25 +105,25 @@ tests/cases/compiler/indexSignatureTypeCheck.ts(73,1): error TS2322: Type '{ [x: !!! error TS2322: Index signature is missing in type '{ [x: number]: string; }'. x = z; ~ -!!! error TS2322: Type '{ [x: number]: number; }' is not assignable to type '{ [x: string]: string; }'. -!!! error TS2322: Index signature is missing in type '{ [x: number]: number; }'. +!!! error TS2322: Type '{ [x: E]: number; }' is not assignable to type '{ [x: string]: string; }'. +!!! error TS2322: Index signature is missing in type '{ [x: E]: number; }'. y = x; y = y; y = z; ~ -!!! error TS2322: Type '{ [x: number]: number; }' is not assignable to type '{ [x: number]: string; }'. +!!! error TS2322: Type '{ [x: E]: number; }' is not assignable to type '{ [x: number]: string; }'. !!! error TS2322: Index signatures are incompatible. !!! error TS2322: Type 'number' is not assignable to type 'string'. z = x; ~ -!!! error TS2322: Type '{ [x: string]: string; }' is not assignable to type '{ [x: number]: number; }'. +!!! error TS2322: Type '{ [x: string]: string; }' is not assignable to type '{ [x: E]: number; }'. !!! error TS2322: Index signatures are incompatible. !!! error TS2322: Type 'string' is not assignable to type 'number'. z = y; ~ -!!! error TS2322: Type '{ [x: number]: string; }' is not assignable to type '{ [x: number]: number; }'. +!!! error TS2322: Type '{ [x: number]: string; }' is not assignable to type '{ [x: E]: number; }'. !!! error TS2322: Index signatures are incompatible. !!! error TS2322: Type 'string' is not assignable to type 'number'. z = z; diff --git a/tests/baselines/reference/indexTypeCheck.errors.txt b/tests/baselines/reference/indexTypeCheck.errors.txt index da3e9e2e26e15..e0a4d528e2ae5 100644 --- a/tests/baselines/reference/indexTypeCheck.errors.txt +++ b/tests/baselines/reference/indexTypeCheck.errors.txt @@ -1,8 +1,8 @@ tests/cases/compiler/indexTypeCheck.ts(2,2): error TS1021: An index signature must have a type annotation. tests/cases/compiler/indexTypeCheck.ts(3,2): error TS1021: An index signature must have a type annotation. -tests/cases/compiler/indexTypeCheck.ts(17,2): error TS2413: Numeric index type 'number' is not assignable to string index type 'string'. -tests/cases/compiler/indexTypeCheck.ts(22,2): error TS2413: Numeric index type 'Orange' is not assignable to string index type 'Yellow'. -tests/cases/compiler/indexTypeCheck.ts(27,2): error TS2413: Numeric index type 'number' is not assignable to string index type 'string'. +tests/cases/compiler/indexTypeCheck.ts(17,2): error TS2413: Numeric index type '[string]: number' is not assignable to string index type '[string]: string'. +tests/cases/compiler/indexTypeCheck.ts(22,2): error TS2413: Numeric index type '[string]: Orange' is not assignable to string index type '[string]: Yellow'. +tests/cases/compiler/indexTypeCheck.ts(27,2): error TS2413: Numeric index type '[string]: number' is not assignable to string index type '[string]: string'. tests/cases/compiler/indexTypeCheck.ts(32,3): error TS1096: An index signature must have exactly one parameter. tests/cases/compiler/indexTypeCheck.ts(36,3): error TS1023: An index signature parameter type must be 'string', 'number', or an enum type. tests/cases/compiler/indexTypeCheck.ts(51,1): error TS2342: An index expression argument must be of type 'string', 'number', 'symbol, or 'any'. @@ -31,21 +31,21 @@ tests/cases/compiler/indexTypeCheck.ts(51,1): error TS2342: An index expression interface Orange { [n:number]: number; // ok ~~~~~~~~~~~~~~~~~~~ -!!! error TS2413: Numeric index type 'number' is not assignable to string index type 'string'. +!!! error TS2413: Numeric index type '[string]: number' is not assignable to string index type '[string]: string'. [s:string]: string; // error } interface Green { [n:number]: Orange; // error ~~~~~~~~~~~~~~~~~~~ -!!! error TS2413: Numeric index type 'Orange' is not assignable to string index type 'Yellow'. +!!! error TS2413: Numeric index type '[string]: Orange' is not assignable to string index type '[string]: Yellow'. [s:string]: Yellow; // ok } interface Cyan { [n:number]: number; // error ~~~~~~~~~~~~~~~~~~~ -!!! error TS2413: Numeric index type 'number' is not assignable to string index type 'string'. +!!! error TS2413: Numeric index type '[string]: number' is not assignable to string index type '[string]: string'. [s:string]: string; // ok } diff --git a/tests/baselines/reference/indexerConstraints.errors.txt b/tests/baselines/reference/indexerConstraints.errors.txt index cb7785535d18a..4f971301b3ec7 100644 --- a/tests/baselines/reference/indexerConstraints.errors.txt +++ b/tests/baselines/reference/indexerConstraints.errors.txt @@ -1,7 +1,7 @@ -tests/cases/compiler/indexerConstraints.ts(17,5): error TS2413: Numeric index type 'A' is not assignable to string index type 'B'. -tests/cases/compiler/indexerConstraints.ts(25,5): error TS2413: Numeric index type 'A' is not assignable to string index type 'B'. -tests/cases/compiler/indexerConstraints.ts(33,5): error TS2413: Numeric index type 'A' is not assignable to string index type 'B'. -tests/cases/compiler/indexerConstraints.ts(41,5): error TS2413: Numeric index type 'A' is not assignable to string index type 'B'. +tests/cases/compiler/indexerConstraints.ts(17,5): error TS2413: Numeric index type '[string]: A' is not assignable to string index type '[string]: B'. +tests/cases/compiler/indexerConstraints.ts(25,5): error TS2413: Numeric index type '[string]: A' is not assignable to string index type '[string]: B'. +tests/cases/compiler/indexerConstraints.ts(33,5): error TS2413: Numeric index type '[string]: A' is not assignable to string index type '[string]: B'. +tests/cases/compiler/indexerConstraints.ts(41,5): error TS2413: Numeric index type '[string]: A' is not assignable to string index type '[string]: B'. ==== tests/cases/compiler/indexerConstraints.ts (4 errors) ==== @@ -23,7 +23,7 @@ tests/cases/compiler/indexerConstraints.ts(41,5): error TS2413: Numeric index ty interface E { [n: number]: A; ~~~~~~~~~~~~~~~ -!!! error TS2413: Numeric index type 'A' is not assignable to string index type 'B'. +!!! error TS2413: Numeric index type '[string]: A' is not assignable to string index type '[string]: B'. } // Inheritance @@ -33,7 +33,7 @@ tests/cases/compiler/indexerConstraints.ts(41,5): error TS2413: Numeric index ty interface G extends F { [n: number]: A; ~~~~~~~~~~~~~~~ -!!! error TS2413: Numeric index type 'A' is not assignable to string index type 'B'. +!!! error TS2413: Numeric index type '[string]: A' is not assignable to string index type '[string]: B'. } // Other way @@ -43,7 +43,7 @@ tests/cases/compiler/indexerConstraints.ts(41,5): error TS2413: Numeric index ty interface I extends H { [s: string]: B; ~~~~~~~~~~~~~~~ -!!! error TS2413: Numeric index type 'A' is not assignable to string index type 'B'. +!!! error TS2413: Numeric index type '[string]: A' is not assignable to string index type '[string]: B'. } // With hidden indexer @@ -53,6 +53,6 @@ tests/cases/compiler/indexerConstraints.ts(41,5): error TS2413: Numeric index ty interface K extends J { [n: number]: A; ~~~~~~~~~~~~~~~ -!!! error TS2413: Numeric index type 'A' is not assignable to string index type 'B'. +!!! error TS2413: Numeric index type '[string]: A' is not assignable to string index type '[string]: B'. [s: string]: B; } \ No newline at end of file diff --git a/tests/baselines/reference/indexerConstraints2.errors.txt b/tests/baselines/reference/indexerConstraints2.errors.txt index 316486e709f96..bc0cf4aa97a49 100644 --- a/tests/baselines/reference/indexerConstraints2.errors.txt +++ b/tests/baselines/reference/indexerConstraints2.errors.txt @@ -1,6 +1,6 @@ -tests/cases/compiler/indexerConstraints2.ts(9,5): error TS2413: Numeric index type 'A' is not assignable to string index type 'B'. -tests/cases/compiler/indexerConstraints2.ts(17,5): error TS2413: Numeric index type 'A' is not assignable to string index type 'B'. -tests/cases/compiler/indexerConstraints2.ts(26,5): error TS2413: Numeric index type 'A' is not assignable to string index type 'B'. +tests/cases/compiler/indexerConstraints2.ts(9,5): error TS2413: Numeric index type '[string]: A' is not assignable to string index type '[string]: B'. +tests/cases/compiler/indexerConstraints2.ts(17,5): error TS2413: Numeric index type '[string]: A' is not assignable to string index type '[string]: B'. +tests/cases/compiler/indexerConstraints2.ts(26,5): error TS2413: Numeric index type '[string]: A' is not assignable to string index type '[string]: B'. ==== tests/cases/compiler/indexerConstraints2.ts (3 errors) ==== @@ -14,7 +14,7 @@ tests/cases/compiler/indexerConstraints2.ts(26,5): error TS2413: Numeric index t class G extends F { [n: number]: A ~~~~~~~~~~~~~~ -!!! error TS2413: Numeric index type 'A' is not assignable to string index type 'B'. +!!! error TS2413: Numeric index type '[string]: A' is not assignable to string index type '[string]: B'. } // Other way @@ -24,7 +24,7 @@ tests/cases/compiler/indexerConstraints2.ts(26,5): error TS2413: Numeric index t class I extends H { [s: string]: B ~~~~~~~~~~~~~~ -!!! error TS2413: Numeric index type 'A' is not assignable to string index type 'B'. +!!! error TS2413: Numeric index type '[string]: A' is not assignable to string index type '[string]: B'. } // With hidden indexer @@ -35,6 +35,6 @@ tests/cases/compiler/indexerConstraints2.ts(26,5): error TS2413: Numeric index t class K extends J { [n: number]: A; ~~~~~~~~~~~~~~~ -!!! error TS2413: Numeric index type 'A' is not assignable to string index type 'B'. +!!! error TS2413: Numeric index type '[string]: A' is not assignable to string index type '[string]: B'. [s: string]: B; } \ No newline at end of file diff --git a/tests/baselines/reference/inheritedStringIndexersFromDifferentBaseTypes2.errors.txt b/tests/baselines/reference/inheritedStringIndexersFromDifferentBaseTypes2.errors.txt index 8e6fc5b3158e3..87f932baf4bfd 100644 --- a/tests/baselines/reference/inheritedStringIndexersFromDifferentBaseTypes2.errors.txt +++ b/tests/baselines/reference/inheritedStringIndexersFromDifferentBaseTypes2.errors.txt @@ -1,12 +1,16 @@ -tests/cases/compiler/inheritedStringIndexersFromDifferentBaseTypes2.ts(18,11): error TS2413: Numeric index type '{}' is not assignable to string index type '{ a: any; }'. +tests/cases/compiler/inheritedStringIndexersFromDifferentBaseTypes2.ts(3,5): error TS2413: Numeric index type '[string]: {}' is not assignable to string index type '[string]: { a: any; }'. ==== tests/cases/compiler/inheritedStringIndexersFromDifferentBaseTypes2.ts (1 errors) ==== // indexer in B is a subtype of indexer in A interface A { [s: string]: { + ~~~~~~~~~~~~~~ a; + ~~~~~~~~~~ }; + ~~~~~~ +!!! error TS2413: Numeric index type '[string]: {}' is not assignable to string index type '[string]: { a: any; }'. } interface B { [s: number]: { @@ -20,8 +24,6 @@ tests/cases/compiler/inheritedStringIndexersFromDifferentBaseTypes2.ts(18,11): e [s: number]: {}; } interface E extends A, D { } // error - ~ -!!! error TS2413: Numeric index type '{}' is not assignable to string index type '{ a: any; }'. interface F extends A, D { [s: number]: { diff --git a/tests/baselines/reference/mergedInterfacesWithIndexers2.errors.txt b/tests/baselines/reference/mergedInterfacesWithIndexers2.errors.txt index 768abc0f9c05e..d46fbf74e2033 100644 --- a/tests/baselines/reference/mergedInterfacesWithIndexers2.errors.txt +++ b/tests/baselines/reference/mergedInterfacesWithIndexers2.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/interfaces/declarationMerging/mergedInterfacesWithIndexers2.ts(4,5): error TS2413: Numeric index type 'string' is not assignable to string index type '{ length: string; }'. +tests/cases/conformance/interfaces/declarationMerging/mergedInterfacesWithIndexers2.ts(4,5): error TS2413: Numeric index type '[string]: string' is not assignable to string index type '[string]: { length: string; }'. tests/cases/conformance/interfaces/declarationMerging/mergedInterfacesWithIndexers2.ts(14,5): error TS2411: Property ''a'' of type 'number' is not assignable to string index type '{ length: number; }'. tests/cases/conformance/interfaces/declarationMerging/mergedInterfacesWithIndexers2.ts(20,5): error TS2412: Property '1' of type '{ length: number; }' is not assignable to numeric index type 'string'. @@ -9,7 +9,7 @@ tests/cases/conformance/interfaces/declarationMerging/mergedInterfacesWithIndexe interface A { [x: number]: string; // error ~~~~~~~~~~~~~~~~~~~~ -!!! error TS2413: Numeric index type 'string' is not assignable to string index type '{ length: string; }'. +!!! error TS2413: Numeric index type '[string]: string' is not assignable to string index type '[string]: { length: string; }'. } diff --git a/tests/baselines/reference/propertiesAndIndexers.errors.txt b/tests/baselines/reference/propertiesAndIndexers.errors.txt index 4ab8bba644c97..468da5fceca4a 100644 --- a/tests/baselines/reference/propertiesAndIndexers.errors.txt +++ b/tests/baselines/reference/propertiesAndIndexers.errors.txt @@ -5,12 +5,9 @@ tests/cases/compiler/propertiesAndIndexers.ts(23,5): error TS2412: Property '4' tests/cases/compiler/propertiesAndIndexers.ts(28,5): error TS2411: Property '1' of type 'Z' is not assignable to string index type 'number'. tests/cases/compiler/propertiesAndIndexers.ts(28,5): error TS2411: Property 'a' of type 'Y' is not assignable to string index type 'number'. tests/cases/compiler/propertiesAndIndexers.ts(28,5): error TS2411: Property 'b' of type 'X' is not assignable to string index type 'number'. +tests/cases/compiler/propertiesAndIndexers.ts(28,5): error TS2413: Numeric index type '[string]: string' is not assignable to string index type '[string]: number'. tests/cases/compiler/propertiesAndIndexers.ts(29,5): error TS2411: Property 'c' of type 'boolean' is not assignable to string index type 'number'. tests/cases/compiler/propertiesAndIndexers.ts(30,5): error TS2411: Property '3' of type 'boolean' is not assignable to string index type 'number'. -tests/cases/compiler/propertiesAndIndexers.ts(33,11): error TS2411: Property '4' of type 'boolean' is not assignable to string index type 'number'. -tests/cases/compiler/propertiesAndIndexers.ts(33,11): error TS2411: Property '5' of type 'string' is not assignable to string index type 'number'. -tests/cases/compiler/propertiesAndIndexers.ts(33,11): error TS2411: Property '6' of type '() => string' is not assignable to string index type 'number'. -tests/cases/compiler/propertiesAndIndexers.ts(33,11): error TS2413: Numeric index type 'string' is not assignable to string index type 'number'. tests/cases/compiler/propertiesAndIndexers.ts(34,5): error TS2411: Property '2' of type 'Z' is not assignable to string index type 'number'. tests/cases/compiler/propertiesAndIndexers.ts(34,5): error TS2412: Property '2' of type 'Z' is not assignable to numeric index type 'string'. tests/cases/compiler/propertiesAndIndexers.ts(35,5): error TS2412: Property 'Infinity' of type 'number' is not assignable to numeric index type 'string'. @@ -19,7 +16,7 @@ tests/cases/compiler/propertiesAndIndexers.ts(44,5): error TS2411: Property 't' tests/cases/compiler/propertiesAndIndexers.ts(50,5): error TS2412: Property '3' of type 'boolean' is not assignable to numeric index type 'string'. -==== tests/cases/compiler/propertiesAndIndexers.ts (19 errors) ==== +==== tests/cases/compiler/propertiesAndIndexers.ts (16 errors) ==== interface X { } interface Y { n: number; @@ -62,6 +59,8 @@ tests/cases/compiler/propertiesAndIndexers.ts(50,5): error TS2412: Property '3' !!! error TS2411: Property 'a' of type 'Y' is not assignable to string index type 'number'. ~~~~~~~~~~~~~~~~~~~~ !!! error TS2411: Property 'b' of type 'X' is not assignable to string index type 'number'. + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2413: Numeric index type '[string]: string' is not assignable to string index type '[string]: number'. c: boolean; ~~~~~~~~~~~ !!! error TS2411: Property 'c' of type 'boolean' is not assignable to string index type 'number'. @@ -71,14 +70,6 @@ tests/cases/compiler/propertiesAndIndexers.ts(50,5): error TS2412: Property '3' } interface D extends B, C { - ~ -!!! error TS2411: Property '4' of type 'boolean' is not assignable to string index type 'number'. - ~ -!!! error TS2411: Property '5' of type 'string' is not assignable to string index type 'number'. - ~ -!!! error TS2411: Property '6' of type '() => string' is not assignable to string index type 'number'. - ~ -!!! error TS2413: Numeric index type 'string' is not assignable to string index type 'number'. 2: Z; ~~~~~ !!! error TS2411: Property '2' of type 'Z' is not assignable to string index type 'number'. diff --git a/tests/baselines/reference/propertiesAndIndexers2.errors.txt b/tests/baselines/reference/propertiesAndIndexers2.errors.txt index e1ab8c9d13d90..b51e4189f4d23 100644 --- a/tests/baselines/reference/propertiesAndIndexers2.errors.txt +++ b/tests/baselines/reference/propertiesAndIndexers2.errors.txt @@ -1,4 +1,5 @@ -tests/cases/compiler/propertiesAndIndexers2.ts(2,5): error TS2413: Numeric index type 'string' is not assignable to string index type 'number'. +tests/cases/compiler/propertiesAndIndexers2.ts(2,5): error TS2413: Numeric index type '[string]: string' is not assignable to string index type '[string]: number'. +tests/cases/compiler/propertiesAndIndexers2.ts(3,5): error TS2413: Numeric index type '[string]: string' is not assignable to string index type '[string]: number'. tests/cases/compiler/propertiesAndIndexers2.ts(8,5): error TS2411: Property 'c' of type 'string' is not assignable to string index type 'number'. tests/cases/compiler/propertiesAndIndexers2.ts(9,5): error TS2411: Property '3' of type 'string' is not assignable to string index type 'number'. tests/cases/compiler/propertiesAndIndexers2.ts(10,5): error TS2411: Property 'Infinity' of type 'string' is not assignable to string index type 'number'. @@ -9,12 +10,14 @@ tests/cases/compiler/propertiesAndIndexers2.ts(14,5): error TS2411: Property '6' tests/cases/compiler/propertiesAndIndexers2.ts(14,5): error TS2412: Property '6' of type '() => string' is not assignable to numeric index type 'string'. -==== tests/cases/compiler/propertiesAndIndexers2.ts (9 errors) ==== +==== tests/cases/compiler/propertiesAndIndexers2.ts (10 errors) ==== interface A { [n: number]: string; ~~~~~~~~~~~~~~~~~~~~ -!!! error TS2413: Numeric index type 'string' is not assignable to string index type 'number'. +!!! error TS2413: Numeric index type '[string]: string' is not assignable to string index type '[string]: number'. [s: string]: number; + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2413: Numeric index type '[string]: string' is not assignable to string index type '[string]: number'. } // All of these should fail.