diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ad23e11fb27..7254f1c2a9d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -51,6 +51,7 @@ namespace ts { const languageVersion = compilerOptions.target || ScriptTarget.ES3; const modulekind = getEmitModuleKind(compilerOptions); const allowSyntheticDefaultImports = typeof compilerOptions.allowSyntheticDefaultImports !== "undefined" ? compilerOptions.allowSyntheticDefaultImports : modulekind === ModuleKind.System; + const strictNullChecks = compilerOptions.strictNullChecks; const emitResolver = createResolver(); @@ -68,10 +69,7 @@ namespace ts { isUnknownSymbol: symbol => symbol === unknownSymbol, getDiagnostics, getGlobalDiagnostics, - - // The language service will always care about the narrowed type of a symbol, because that is - // the type the language says the symbol should have. - getTypeOfSymbolAtLocation: getNarrowedTypeOfSymbol, + getTypeOfSymbolAtLocation, getSymbolsOfParameterPropertyDeclaration, getDeclaredTypeOfSymbol, getPropertiesOfType, @@ -109,14 +107,16 @@ namespace ts { const unknownSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "unknown"); const resolvingSymbol = createSymbol(SymbolFlags.Transient, "__resolving__"); + const nullableWideningFlags = strictNullChecks ? 0 : TypeFlags.ContainsUndefinedOrNull; const anyType = createIntrinsicType(TypeFlags.Any, "any"); const stringType = createIntrinsicType(TypeFlags.String, "string"); const numberType = createIntrinsicType(TypeFlags.Number, "number"); const booleanType = createIntrinsicType(TypeFlags.Boolean, "boolean"); const esSymbolType = createIntrinsicType(TypeFlags.ESSymbol, "symbol"); const voidType = createIntrinsicType(TypeFlags.Void, "void"); - const undefinedType = createIntrinsicType(TypeFlags.Undefined | TypeFlags.ContainsUndefinedOrNull, "undefined"); - const nullType = createIntrinsicType(TypeFlags.Null | TypeFlags.ContainsUndefinedOrNull, "null"); + const undefinedType = createIntrinsicType(TypeFlags.Undefined | nullableWideningFlags, "undefined"); + const nullType = createIntrinsicType(TypeFlags.Null | nullableWideningFlags, "null"); + const emptyArrayElementType = createIntrinsicType(TypeFlags.Undefined | TypeFlags.ContainsUndefinedOrNull, "undefined"); const unknownType = createIntrinsicType(TypeFlags.Any, "unknown"); const emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); @@ -229,6 +229,7 @@ namespace ts { const subtypeRelation: Map = {}; const assignableRelation: Map = {}; + const comparableRelation: Map = {}; const identityRelation: Map = {}; // This is for caching the result of getSymbolDisplayBuilder. Do not access directly. @@ -2703,6 +2704,11 @@ namespace ts { type = createArrayType(elementType); } } + // In strict null checking mode, if a default value of a non-undefined type is specified, remove + // undefined from the final type. + if (strictNullChecks && declaration.initializer && !(getNullableKind(checkExpressionCached(declaration.initializer)) & TypeFlags.Undefined)) { + type = removeNullableKind(type, TypeFlags.Undefined); + } return type; } @@ -2773,7 +2779,8 @@ namespace ts { // Use type from type annotation if one is present if (declaration.type) { - return getTypeFromTypeNode(declaration.type); + const type = getTypeFromTypeNode(declaration.type); + return strictNullChecks && declaration.questionToken ? addNullableKind(type, TypeFlags.Undefined) : type; } if (declaration.kind === SyntaxKind.Parameter) { @@ -2788,7 +2795,7 @@ namespace ts { // Use contextual parameter type if one is available const type = getContextuallyTypedParameterType(declaration); if (type) { - return type; + return strictNullChecks && declaration.questionToken ? addNullableKind(type, TypeFlags.Undefined) : type; } } @@ -3498,6 +3505,8 @@ namespace ts { case SyntaxKind.BooleanKeyword: case SyntaxKind.SymbolKeyword: case SyntaxKind.VoidKeyword: + case SyntaxKind.UndefinedKeyword: + case SyntaxKind.NullKeyword: case SyntaxKind.StringLiteralType: return true; case SyntaxKind.ArrayType: @@ -4507,10 +4516,12 @@ namespace ts { // It is only necessary to do so if a constituent type might be the undefined type, the null type, the type // of an object literal or the anyFunctionType. This is because there are operations in the type checker // that care about the presence of such types at arbitrary depth in a containing type. - function getPropagatingFlagsOfTypes(types: Type[]): TypeFlags { + function getPropagatingFlagsOfTypes(types: Type[], excludeKinds: TypeFlags): TypeFlags { let result: TypeFlags = 0; for (const type of types) { - result |= type.flags; + if (!(type.flags & excludeKinds)) { + result |= type.flags; + } } return result & TypeFlags.PropagatingFlags; } @@ -4519,7 +4530,8 @@ namespace ts { const id = getTypeListId(typeArguments); let type = target.instantiations[id]; if (!type) { - const flags = TypeFlags.Reference | (typeArguments ? getPropagatingFlagsOfTypes(typeArguments) : 0); + const propagatedFlags = typeArguments ? getPropagatingFlagsOfTypes(typeArguments, /*excludeKinds*/ 0) : 0; + const flags = TypeFlags.Reference | propagatedFlags; type = target.instantiations[id] = createObjectType(flags, target.symbol); type.target = target; type.typeArguments = typeArguments; @@ -4779,7 +4791,8 @@ namespace ts { } function createNewTupleType(elementTypes: Type[]) { - const type = createObjectType(TypeFlags.Tuple | getPropagatingFlagsOfTypes(elementTypes)); + const propagatedFlags = getPropagatingFlagsOfTypes(elementTypes, /*excludeKinds*/ 0); + const type = createObjectType(TypeFlags.Tuple | propagatedFlags); type.elementTypes = elementTypes; return type; } @@ -4792,10 +4805,21 @@ namespace ts { return links.resolvedType; } - function addTypeToSet(typeSet: Type[], type: Type, typeSetKind: TypeFlags) { + interface TypeSet extends Array { + containsAny?: boolean; + containsUndefined?: boolean; + containsNull?: boolean; + } + + function addTypeToSet(typeSet: TypeSet, type: Type, typeSetKind: TypeFlags) { if (type.flags & typeSetKind) { addTypesToSet(typeSet, (type).types, typeSetKind); } + else if (type.flags & (TypeFlags.Any | TypeFlags.Undefined | TypeFlags.Null)) { + if (type.flags & TypeFlags.Any) typeSet.containsAny = true; + if (type.flags & TypeFlags.Undefined) typeSet.containsUndefined = true; + if (type.flags & TypeFlags.Null) typeSet.containsNull = true; + } else if (!contains(typeSet, type)) { typeSet.push(type); } @@ -4803,7 +4827,7 @@ namespace ts { // Add the given types to the given type set. Order is preserved, duplicates are removed, // and nested types of the given kind are flattened into the set. - function addTypesToSet(typeSet: Type[], types: Type[], typeSetKind: TypeFlags) { + function addTypesToSet(typeSet: TypeSet, types: Type[], typeSetKind: TypeFlags) { for (const type of types) { addTypeToSet(typeSet, type, typeSetKind); } @@ -4828,25 +4852,6 @@ namespace ts { } } - function containsTypeAny(types: Type[]): boolean { - for (const type of types) { - if (isTypeAny(type)) { - return true; - } - } - return false; - } - - function removeAllButLast(types: Type[], typeToRemove: Type) { - let i = types.length; - while (i > 0 && types.length > 1) { - i--; - if (types[i] === typeToRemove) { - types.splice(i, 1); - } - } - } - // We reduce the constituent type set to only include types that aren't subtypes of other types, unless // the noSubtypeReduction flag is specified, in which case we perform a simple deduplication based on // object identity. Subtype reduction is possible only when union types are known not to circularly @@ -4858,25 +4863,29 @@ namespace ts { if (types.length === 0) { return emptyUnionType; } - const typeSet: Type[] = []; + const typeSet = [] as TypeSet; addTypesToSet(typeSet, types, TypeFlags.Union); - if (containsTypeAny(typeSet)) { + if (typeSet.containsAny) { return anyType; } - if (noSubtypeReduction) { - removeAllButLast(typeSet, undefinedType); - removeAllButLast(typeSet, nullType); + if (strictNullChecks) { + if (typeSet.containsNull) typeSet.push(nullType); + if (typeSet.containsUndefined) typeSet.push(undefinedType); } - else { + if (!noSubtypeReduction) { removeSubtypes(typeSet); } - if (typeSet.length === 1) { + if (typeSet.length === 0) { + return typeSet.containsNull ? nullType : undefinedType; + } + else if (typeSet.length === 1) { return typeSet[0]; } const id = getTypeListId(typeSet); let type = unionTypes[id]; if (!type) { - type = unionTypes[id] = createObjectType(TypeFlags.Union | getPropagatingFlagsOfTypes(typeSet)); + const propagatedFlags = getPropagatingFlagsOfTypes(typeSet, /*excludeKinds*/ TypeFlags.Nullable); + type = unionTypes[id] = createObjectType(TypeFlags.Union | propagatedFlags); type.types = typeSet; } return type; @@ -4899,18 +4908,23 @@ namespace ts { if (types.length === 0) { return emptyObjectType; } - const typeSet: Type[] = []; + const typeSet = [] as TypeSet; addTypesToSet(typeSet, types, TypeFlags.Intersection); - if (containsTypeAny(typeSet)) { + if (typeSet.containsAny) { return anyType; } + if (strictNullChecks) { + if (typeSet.containsNull) typeSet.push(nullType); + if (typeSet.containsUndefined) typeSet.push(undefinedType); + } if (typeSet.length === 1) { return typeSet[0]; } const id = getTypeListId(typeSet); let type = intersectionTypes[id]; if (!type) { - type = intersectionTypes[id] = createObjectType(TypeFlags.Intersection | getPropagatingFlagsOfTypes(typeSet)); + const propagatedFlags = getPropagatingFlagsOfTypes(typeSet, /*excludeKinds*/ TypeFlags.Nullable); + type = intersectionTypes[id] = createObjectType(TypeFlags.Intersection | propagatedFlags); type.types = typeSet; } return type; @@ -5006,6 +5020,10 @@ namespace ts { return esSymbolType; case SyntaxKind.VoidKeyword: return voidType; + case SyntaxKind.UndefinedKeyword: + return undefinedType; + case SyntaxKind.NullKeyword: + return nullType; case SyntaxKind.ThisType: return getTypeFromThisTypeNode(node); case SyntaxKind.StringLiteralType: @@ -5379,6 +5397,10 @@ namespace ts { return checkTypeAssignableTo(source, target, /*errorNode*/ undefined); } + function isTypeComparableTo(source: Type, target: Type): boolean { + return checkTypeComparableTo(source, target, /*errorNode*/ undefined); + } + function checkTypeSubtypeOf(source: Type, target: Type, errorNode: Node, headMessage?: DiagnosticMessage, containingMessageChain?: DiagnosticMessageChain): boolean { return checkTypeRelatedTo(source, target, subtypeRelation, errorNode, headMessage, containingMessageChain); } @@ -5387,6 +5409,10 @@ namespace ts { return checkTypeRelatedTo(source, target, assignableRelation, errorNode, headMessage, containingMessageChain); } + function checkTypeComparableTo(source: Type, target: Type, errorNode: Node, headMessage?: DiagnosticMessage, containingMessageChain?: DiagnosticMessageChain): boolean { + return checkTypeRelatedTo(source, target, comparableRelation, errorNode, headMessage, containingMessageChain); + } + function isSignatureAssignableTo(source: Signature, target: Signature, ignoreReturnTypes: boolean): boolean { @@ -5423,8 +5449,8 @@ namespace ts { const sourceParams = source.parameters; const targetParams = target.parameters; for (let i = 0; i < checkCount; i++) { - const s = i < sourceMax ? getTypeOfSymbol(sourceParams[i]) : getRestTypeOfSignature(source); - const t = i < targetMax ? getTypeOfSymbol(targetParams[i]) : getRestTypeOfSignature(target); + const s = i < sourceMax ? getTypeOfParameter(sourceParams[i]) : getRestTypeOfSignature(source); + const t = i < targetMax ? getTypeOfParameter(targetParams[i]) : getRestTypeOfSignature(target); const related = compareTypes(s, t, /*reportErrors*/ false) || compareTypes(t, s, reportErrors); if (!related) { if (reportErrors) { @@ -5544,7 +5570,7 @@ namespace ts { * Checks if 'source' is related to 'target' (e.g.: is a assignable to). * @param source The left-hand-side of the relation. * @param target The right-hand-side of the relation. - * @param relation The relation considered. One of 'identityRelation', 'assignableRelation', or 'subTypeRelation'. + * @param relation The relation considered. One of 'identityRelation', 'subtypeRelation', 'assignableRelation', or 'comparableRelation'. * Used as both to determine which checks are performed and as a cache of previously computed results. * @param errorNode The suggested node upon which all errors will be reported, if defined. This may or may not be the actual node used. * @param headMessage If the error chain should be prepended by a head message, then headMessage will be used. @@ -5609,8 +5635,12 @@ namespace ts { } if (isTypeAny(target)) return Ternary.True; - if (source === undefinedType) return Ternary.True; - if (source === nullType && target !== undefinedType) return Ternary.True; + if (source.flags & TypeFlags.Undefined) { + if (!strictNullChecks || target.flags & (TypeFlags.Undefined | TypeFlags.Void) || source === emptyArrayElementType) return Ternary.True; + } + if (source.flags & TypeFlags.Null) { + if (!strictNullChecks || target.flags & TypeFlags.Null) return Ternary.True; + } if (source.flags & TypeFlags.Enum && target === numberType) return Ternary.True; if (source.flags & TypeFlags.Enum && target.flags & TypeFlags.Enum) { if (result = enumRelatedTo(source, target)) { @@ -5618,7 +5648,7 @@ namespace ts { } } if (source.flags & TypeFlags.StringLiteral && target === stringType) return Ternary.True; - if (relation === assignableRelation) { + if (relation === assignableRelation || relation === comparableRelation) { if (isTypeAny(source)) return Ternary.True; if (source === numberType && target.flags & TypeFlags.Enum) return Ternary.True; } @@ -5646,8 +5676,15 @@ namespace ts { // Note that the "each" checks must precede the "some" checks to produce the correct results if (source.flags & TypeFlags.Union) { - if (result = eachTypeRelatedToType(source, target, reportErrors)) { - return result; + if (relation === comparableRelation) { + if (result = someTypeRelatedToType(source, target, reportErrors)) { + return result; + } + } + else { + if (result = eachTypeRelatedToType(source, target, reportErrors)) { + return result; + } } } else if (target.flags & TypeFlags.Intersection) { @@ -5678,7 +5715,7 @@ namespace ts { } } if (target.flags & TypeFlags.Union) { - if (result = typeRelatedToSomeType(source, target, reportErrors)) { + if (result = typeRelatedToSomeType(source, target, reportErrors && !(source.flags & TypeFlags.Primitive))) { return result; } } @@ -5754,7 +5791,8 @@ namespace ts { function isKnownProperty(type: Type, name: string): boolean { if (type.flags & TypeFlags.ObjectType) { const resolved = resolveStructuredTypeMembers(type); - if (relation === assignableRelation && (type === globalObjectType || resolved.properties.length === 0) || + if ((relation === assignableRelation || relation === comparableRelation) && + (type === globalObjectType || resolved.properties.length === 0) || resolved.stringIndexInfo || resolved.numberIndexInfo || getPropertyOfType(type, name)) { return true; } @@ -5804,7 +5842,19 @@ namespace ts { function typeRelatedToSomeType(source: Type, target: UnionOrIntersectionType, reportErrors: boolean): Ternary { const targetTypes = target.types; - for (let i = 0, len = targetTypes.length; i < len; i++) { + let len = targetTypes.length; + // The null and undefined types are guaranteed to be at the end of the constituent type list. In order + // to produce the best possible errors we first check the nullable types, such that the last type we + // check and report errors from is a non-nullable type if one is present. + while (len >= 2 && targetTypes[len - 1].flags & TypeFlags.Nullable) { + const related = isRelatedTo(source, targetTypes[len - 1], /*reportErrors*/ false); + if (related) { + return related; + } + len--; + } + // Now check the non-nullable types and report errors on the last one. + for (let i = 0; i < len; i++) { const related = isRelatedTo(source, targetTypes[i], reportErrors && i === len - 1); if (related) { return related; @@ -5828,7 +5878,19 @@ namespace ts { function someTypeRelatedToType(source: UnionOrIntersectionType, target: Type, reportErrors: boolean): Ternary { const sourceTypes = source.types; - for (let i = 0, len = sourceTypes.length; i < len; i++) { + let len = sourceTypes.length; + // The null and undefined types are guaranteed to be at the end of the constituent type list. In order + // to produce the best possible errors we first check the nullable types, such that the last type we + // check and report errors from is a non-nullable type if one is present. + while (len >= 2 && sourceTypes[len - 1].flags & TypeFlags.Nullable) { + const related = isRelatedTo(sourceTypes[len - 1], target, /*reportErrors*/ false); + if (related) { + return related; + } + len--; + } + // Now check the non-nullable types and report errors on the last one. + for (let i = 0; i < len; i++) { const related = isRelatedTo(sourceTypes[i], target, reportErrors && i === len - 1); if (related) { return related; @@ -6368,8 +6430,8 @@ namespace ts { let result = Ternary.True; const targetLen = target.parameters.length; for (let i = 0; i < targetLen; i++) { - const s = isRestParameterIndex(source, i) ? getRestTypeOfSignature(source) : getTypeOfSymbol(source.parameters[i]); - const t = isRestParameterIndex(target, i) ? getRestTypeOfSignature(target) : getTypeOfSymbol(target.parameters[i]); + const s = isRestParameterIndex(source, i) ? getRestTypeOfSignature(source) : getTypeOfParameter(source.parameters[i]); + const t = isRestParameterIndex(target, i) ? getRestTypeOfSignature(target) : getTypeOfParameter(target.parameters[i]); const related = compareTypes(s, t); if (!related) { return Ternary.False; @@ -6387,14 +6449,30 @@ namespace ts { } function isSupertypeOfEach(candidate: Type, types: Type[]): boolean { - for (const type of types) { - if (candidate !== type && !isTypeSubtypeOf(type, candidate)) return false; + for (const t of types) { + if (candidate !== t && !isTypeSubtypeOf(t, candidate)) return false; } return true; } + function getCombinedFlagsOfTypes(types: Type[]) { + let flags: TypeFlags = 0; + for (const t of types) { + flags |= t.flags; + } + return flags; + } + function getCommonSupertype(types: Type[]): Type { - return forEach(types, t => isSupertypeOfEach(t, types) ? t : undefined); + if (!strictNullChecks) { + return forEach(types, t => isSupertypeOfEach(t, types) ? t : undefined); + } + const primaryTypes = filter(types, t => !(t.flags & TypeFlags.Nullable)); + if (!primaryTypes.length) { + return getUnionType(types); + } + const supertype = forEach(primaryTypes, t => isSupertypeOfEach(t, primaryTypes) ? t : undefined); + return supertype && addNullableKind(supertype, getCombinedFlagsOfTypes(types) & TypeFlags.Nullable); } function reportNoCommonSupertypeError(types: Type[], errorLocation: Node, errorMessageChainHead: DiagnosticMessageChain): void { @@ -6446,7 +6524,7 @@ namespace ts { // A type is array-like if it is a reference to the global Array or global ReadonlyArray type, // or if it is not the undefined or null type and if it is assignable to ReadonlyArray return type.flags & TypeFlags.Reference && ((type).target === globalArrayType || (type).target === globalReadonlyArrayType) || - !(type.flags & (TypeFlags.Undefined | TypeFlags.Null)) && isTypeAssignableTo(type, anyReadonlyArrayType); + !(type.flags & TypeFlags.Nullable) && isTypeAssignableTo(type, anyReadonlyArrayType); } function isTupleLikeType(type: Type): boolean { @@ -6465,6 +6543,63 @@ namespace ts { return !!(type.flags & TypeFlags.Tuple); } + function getNullableKind(type: Type): TypeFlags { + let flags = type.flags; + if (flags & TypeFlags.Union) { + for (const t of (type as UnionType).types) { + flags |= t.flags; + } + } + return flags & TypeFlags.Nullable; + } + + function getNullableTypeOfKind(kind: TypeFlags) { + return kind & TypeFlags.Null ? kind & TypeFlags.Undefined ? + getUnionType([nullType, undefinedType]) : nullType : undefinedType; + } + + function addNullableKind(type: Type, kind: TypeFlags): Type { + if ((getNullableKind(type) & kind) !== kind) { + const types = [type]; + if (kind & TypeFlags.Undefined) { + types.push(undefinedType); + } + if (kind & TypeFlags.Null) { + types.push(nullType); + } + type = getUnionType(types); + } + return type; + } + + function removeNullableKind(type: Type, kind: TypeFlags) { + if (type.flags & TypeFlags.Union && getNullableKind(type) & kind) { + let firstType: Type; + let types: Type[]; + for (const t of (type as UnionType).types) { + if (!(t.flags & kind)) { + if (!firstType) { + firstType = t; + } + else { + if (!types) { + types = [firstType]; + } + types.push(t); + } + } + } + if (firstType) { + type = types ? getUnionType(types) : firstType; + } + } + return type; + } + + function getNonNullableType(type: Type): Type { + return strictNullChecks ? removeNullableKind(type, TypeFlags.Nullable) : type; + } + /** * Return true if type was inferred from an object literal or written as an object type literal * with no call or construct signatures. @@ -6518,16 +6653,20 @@ namespace ts { numberIndexInfo && createIndexInfo(getWidenedType(numberIndexInfo.type), numberIndexInfo.isReadonly)); } + function getWidenedConstituentType(type: Type): Type { + return type.flags & TypeFlags.Nullable ? type : getWidenedType(type); + } + function getWidenedType(type: Type): Type { if (type.flags & TypeFlags.RequiresWidening) { - if (type.flags & (TypeFlags.Undefined | TypeFlags.Null)) { + if (type.flags & TypeFlags.Nullable) { return anyType; } if (type.flags & TypeFlags.ObjectLiteral) { return getWidenedTypeOfObjectLiteral(type); } if (type.flags & TypeFlags.Union) { - return getUnionType(map((type).types, getWidenedType), /*noSubtypeReduction*/ true); + return getUnionType(map((type).types, getWidenedConstituentType), /*noSubtypeReduction*/ true); } if (isArrayType(type)) { return createArrayType(getWidenedType((type).typeArguments[0])); @@ -6645,8 +6784,8 @@ namespace ts { count = sourceMax < targetMax ? sourceMax : targetMax; } for (let i = 0; i < count; i++) { - const s = i < sourceMax ? getTypeOfSymbol(source.parameters[i]) : getRestTypeOfSignature(source); - const t = i < targetMax ? getTypeOfSymbol(target.parameters[i]) : getRestTypeOfSignature(target); + const s = i < sourceMax ? getTypeOfParameter(source.parameters[i]) : getRestTypeOfSignature(source); + const t = i < targetMax ? getTypeOfParameter(target.parameters[i]) : getRestTypeOfSignature(target); callback(s, t); } } @@ -6673,7 +6812,6 @@ namespace ts { function inferTypes(context: InferenceContext, source: Type, target: Type) { let sourceStack: Type[]; let targetStack: Type[]; - const maxDepth = 5; let depth = 0; let inferiority = 0; const visited: Map = {}; @@ -6802,11 +6940,6 @@ namespace ts { if (isInProcess(source, target)) { return; } - // we delibirately limit the depth we examine to infer types: this speeds up the overall inference process - // and user rarely expects inferences to be made from the deeply nested constituents. - if (depth > maxDepth) { - return; - } if (isDeeplyNestedGeneric(source, sourceStack, depth) && isDeeplyNestedGeneric(target, targetStack, depth)) { return; } @@ -6964,10 +7097,22 @@ namespace ts { // EXPRESSION TYPE CHECKING + function createTransientIdentifier(symbol: Symbol, location: Node): Identifier { + const result = createNode(SyntaxKind.Identifier); + result.text = symbol.name; + result.resolvedSymbol = symbol; + result.parent = location; + result.id = -1; + return result; + } + function getResolvedSymbol(node: Identifier): Symbol { + if (node.id === -1) { + return (node).resolvedSymbol; + } const links = getNodeLinks(node); if (!links.resolvedSymbol) { - links.resolvedSymbol = (!nodeIsMissing(node) && resolveName(node, node.text, SymbolFlags.Value | SymbolFlags.ExportValue, Diagnostics.Cannot_find_name_0, node)) || unknownSymbol; + links.resolvedSymbol = !nodeIsMissing(node) && resolveName(node, node.text, SymbolFlags.Value | SymbolFlags.ExportValue, Diagnostics.Cannot_find_name_0, node) || unknownSymbol; } return links.resolvedSymbol; } @@ -6991,58 +7136,74 @@ namespace ts { Debug.fail("should not get here"); } + // Return the assignment key for a "dotted name" (i.e. a sequence of identifiers + // separated by dots). The key consists of the id of the symbol referenced by the + // leftmost identifier followed by zero or more property names separated by dots. + // The result is undefined if the reference isn't a dotted name. + function getAssignmentKey(node: Node): string { + if (node.kind === SyntaxKind.Identifier) { + const symbol = getResolvedSymbol(node); + return symbol !== unknownSymbol ? "" + getSymbolId(symbol) : undefined; + } + if (node.kind === SyntaxKind.ThisKeyword) { + return "0"; + } + if (node.kind === SyntaxKind.PropertyAccessExpression) { + const key = getAssignmentKey((node).expression); + return key && key + "." + (node).name.text; + } + return undefined; + } + function hasInitializer(node: VariableLikeDeclaration): boolean { return !!(node.initializer || isBindingPattern(node.parent) && hasInitializer(node.parent.parent)); } - // Check if a given variable is assigned within a given syntax node - function isVariableAssignedWithin(symbol: Symbol, node: Node): boolean { - const links = getNodeLinks(node); - if (links.assignmentChecks) { - const cachedResult = links.assignmentChecks[symbol.id]; - if (cachedResult !== undefined) { - return cachedResult; - } - } - else { - links.assignmentChecks = {}; - } - return links.assignmentChecks[symbol.id] = isAssignedIn(node); + // For a given node compute a map of which dotted names are assigned within + // the node. + function getAssignmentMap(node: Node): Map { + const assignmentMap: Map = {}; + visit(node); + return assignmentMap; - function isAssignedInBinaryExpression(node: BinaryExpression) { - if (node.operatorToken.kind >= SyntaxKind.FirstAssignment && node.operatorToken.kind <= SyntaxKind.LastAssignment) { - const n = skipParenthesizedNodes(node.left); - if (n.kind === SyntaxKind.Identifier && getResolvedSymbol(n) === symbol) { - return true; + function visitReference(node: Identifier | PropertyAccessExpression) { + if (isAssignmentTarget(node) || isCompoundAssignmentTarget(node)) { + const key = getAssignmentKey(node); + if (key) { + assignmentMap[key] = true; } } - return forEachChild(node, isAssignedIn); + forEachChild(node, visit); } - function isAssignedInVariableDeclaration(node: VariableLikeDeclaration) { - if (!isBindingPattern(node.name) && getSymbolOfNode(node) === symbol && hasInitializer(node)) { - return true; + function visitVariableDeclaration(node: VariableLikeDeclaration) { + if (!isBindingPattern(node.name) && hasInitializer(node)) { + assignmentMap[getSymbolId(getSymbolOfNode(node))] = true; } - return forEachChild(node, isAssignedIn); + forEachChild(node, visit); } - function isAssignedIn(node: Node): boolean { + function visit(node: Node) { switch (node.kind) { - case SyntaxKind.BinaryExpression: - return isAssignedInBinaryExpression(node); + case SyntaxKind.Identifier: + case SyntaxKind.PropertyAccessExpression: + visitReference(node); + break; case SyntaxKind.VariableDeclaration: case SyntaxKind.BindingElement: - return isAssignedInVariableDeclaration(node); + visitVariableDeclaration(node); + break; + case SyntaxKind.BinaryExpression: case SyntaxKind.ObjectBindingPattern: case SyntaxKind.ArrayBindingPattern: case SyntaxKind.ArrayLiteralExpression: case SyntaxKind.ObjectLiteralExpression: - case SyntaxKind.PropertyAccessExpression: case SyntaxKind.ElementAccessExpression: case SyntaxKind.CallExpression: case SyntaxKind.NewExpression: case SyntaxKind.TypeAssertionExpression: case SyntaxKind.AsExpression: + case SyntaxKind.NonNullExpression: case SyntaxKind.ParenthesizedExpression: case SyntaxKind.PrefixUnaryExpression: case SyntaxKind.DeleteExpression: @@ -7065,6 +7226,7 @@ namespace ts { case SyntaxKind.ReturnStatement: case SyntaxKind.WithStatement: case SyntaxKind.SwitchStatement: + case SyntaxKind.CaseBlock: case SyntaxKind.CaseClause: case SyntaxKind.DefaultClause: case SyntaxKind.LabeledStatement: @@ -7077,98 +7239,210 @@ namespace ts { case SyntaxKind.JsxSpreadAttribute: case SyntaxKind.JsxOpeningElement: case SyntaxKind.JsxExpression: - return forEachChild(node, isAssignedIn); + forEachChild(node, visit); + break; } - return false; } } - // Get the narrowed type of a given symbol at a given location - function getNarrowedTypeOfSymbol(symbol: Symbol, node: Node) { - let type = getTypeOfSymbol(symbol); - // Only narrow when symbol is variable of type any or an object, union, or type parameter type - if (node && symbol.flags & SymbolFlags.Variable) { - if (isTypeAny(type) || type.flags & (TypeFlags.ObjectType | TypeFlags.Union | TypeFlags.TypeParameter)) { - const declaration = getDeclarationOfKind(symbol, SyntaxKind.VariableDeclaration); - const top = declaration && getDeclarationContainer(declaration); - const originalType = type; - const nodeStack: {node: Node, child: Node}[] = []; - loop: while (node.parent) { - const child = node; - node = node.parent; - switch (node.kind) { - case SyntaxKind.IfStatement: - case SyntaxKind.ConditionalExpression: - case SyntaxKind.BinaryExpression: - nodeStack.push({node, child}); - break; - case SyntaxKind.SourceFile: - case SyntaxKind.ModuleDeclaration: - // Stop at the first containing file or module declaration - break loop; - } - if (node === top) { - break; - } - } - - let nodes: {node: Node, child: Node}; - while (nodes = nodeStack.pop()) { - const {node, child} = nodes; - switch (node.kind) { - case SyntaxKind.IfStatement: - // In a branch of an if statement, narrow based on controlling expression - if (child !== (node).expression) { - type = narrowType(type, (node).expression, /*assumeTrue*/ child === (node).thenStatement); - } - break; - case SyntaxKind.ConditionalExpression: - // In a branch of a conditional expression, narrow based on controlling condition - if (child !== (node).condition) { - type = narrowType(type, (node).condition, /*assumeTrue*/ child === (node).whenTrue); - } - break; - case SyntaxKind.BinaryExpression: - // In the right operand of an && or ||, narrow based on left operand - if (child === (node).right) { - if ((node).operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) { - type = narrowType(type, (node).left, /*assumeTrue*/ true); - } - else if ((node).operatorToken.kind === SyntaxKind.BarBarToken) { - type = narrowType(type, (node).left, /*assumeTrue*/ false); - } - } - break; - default: - Debug.fail("Unreachable!"); - } - - // Use original type if construct contains assignments to variable - if (type !== originalType && isVariableAssignedWithin(symbol, node)) { - type = originalType; - } - } - - // Preserve old top-level behavior - if the branch is really an empty set, revert to prior type - if (type === emptyUnionType) { - type = originalType; - } + function isReferenceAssignedWithin(reference: Node, node: Node): boolean { + if (reference.kind !== SyntaxKind.ThisKeyword) { + const key = getAssignmentKey(reference); + if (key) { + const links = getNodeLinks(node); + return (links.assignmentMap || (links.assignmentMap = getAssignmentMap(node)))[key]; } } + return false; + } + + function isAnyPartOfReferenceAssignedWithin(reference: Node, node: Node) { + while (true) { + if (isReferenceAssignedWithin(reference, node)) { + return true; + } + if (reference.kind !== SyntaxKind.PropertyAccessExpression) { + return false; + } + reference = (reference).expression; + } + } + + function isNullOrUndefinedLiteral(node: Expression) { + return node.kind === SyntaxKind.NullKeyword || + node.kind === SyntaxKind.Identifier && getResolvedSymbol(node) === undefinedSymbol; + } + + function getLeftmostIdentifierOrThis(node: Node): Node { + switch (node.kind) { + case SyntaxKind.Identifier: + case SyntaxKind.ThisKeyword: + return node; + case SyntaxKind.PropertyAccessExpression: + return getLeftmostIdentifierOrThis((node).expression); + } + return undefined; + } + + function isMatchingReference(source: Node, target: Node): boolean { + if (source.kind === target.kind) { + switch (source.kind) { + case SyntaxKind.Identifier: + return getResolvedSymbol(source) === getResolvedSymbol(target); + case SyntaxKind.ThisKeyword: + return true; + case SyntaxKind.PropertyAccessExpression: + return (source).name.text === (target).name.text && + isMatchingReference((source).expression, (target).expression); + } + } + return false; + } + + // Get the narrowed type of a given symbol at a given location + function getNarrowedTypeOfReference(type: Type, reference: Node) { + if (!(type.flags & (TypeFlags.Any | TypeFlags.ObjectType | TypeFlags.Union | TypeFlags.TypeParameter))) { + return type; + } + const leftmostNode = getLeftmostIdentifierOrThis(reference); + if (!leftmostNode) { + return type; + } + let top: Node; + if (leftmostNode.kind === SyntaxKind.Identifier) { + const leftmostSymbol = getExportSymbolOfValueSymbolIfExported(getResolvedSymbol(leftmostNode)); + if (!leftmostSymbol) { + return type; + } + const declaration = leftmostSymbol.valueDeclaration; + if (!declaration || declaration.kind !== SyntaxKind.VariableDeclaration && declaration.kind !== SyntaxKind.Parameter && declaration.kind !== SyntaxKind.BindingElement) { + return type; + } + top = getDeclarationContainer(declaration); + } + const originalType = type; + const nodeStack: { node: Node, child: Node }[] = []; + let node: Node = reference; + loop: while (node.parent) { + const child = node; + node = node.parent; + switch (node.kind) { + case SyntaxKind.IfStatement: + case SyntaxKind.ConditionalExpression: + case SyntaxKind.BinaryExpression: + nodeStack.push({node, child}); + break; + case SyntaxKind.SourceFile: + case SyntaxKind.ModuleDeclaration: + break loop; + default: + if (node === top || isFunctionLikeKind(node.kind)) { + break loop; + } + break; + } + } + + let nodes: { node: Node, child: Node }; + while (nodes = nodeStack.pop()) { + const {node, child} = nodes; + switch (node.kind) { + case SyntaxKind.IfStatement: + // In a branch of an if statement, narrow based on controlling expression + if (child !== (node).expression) { + type = narrowType(type, (node).expression, /*assumeTrue*/ child === (node).thenStatement); + } + break; + case SyntaxKind.ConditionalExpression: + // In a branch of a conditional expression, narrow based on controlling condition + if (child !== (node).condition) { + type = narrowType(type, (node).condition, /*assumeTrue*/ child === (node).whenTrue); + } + break; + case SyntaxKind.BinaryExpression: + // In the right operand of an && or ||, narrow based on left operand + if (child === (node).right) { + if ((node).operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) { + type = narrowType(type, (node).left, /*assumeTrue*/ true); + } + else if ((node).operatorToken.kind === SyntaxKind.BarBarToken) { + type = narrowType(type, (node).left, /*assumeTrue*/ false); + } + } + break; + default: + Debug.fail("Unreachable!"); + } + + // Use original type if construct contains assignments to variable + if (type !== originalType && isAnyPartOfReferenceAssignedWithin(reference, node)) { + type = originalType; + } + } + + // Preserve old top-level behavior - if the branch is really an empty set, revert to prior type + if (type === emptyUnionType) { + type = originalType; + } return type; - function narrowTypeByEquality(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type { - // Check that we have 'typeof ' on the left and string literal on the right - if (expr.left.kind !== SyntaxKind.TypeOfExpression || expr.right.kind !== SyntaxKind.StringLiteral) { + function narrowTypeByTruthiness(type: Type, expr: Expression, assumeTrue: boolean): Type { + return strictNullChecks && assumeTrue && isMatchingReference(expr, reference) ? getNonNullableType(type) : type; + } + + function narrowTypeByBinaryExpression(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type { + switch (expr.operatorToken.kind) { + case SyntaxKind.EqualsEqualsToken: + case SyntaxKind.ExclamationEqualsToken: + case SyntaxKind.EqualsEqualsEqualsToken: + case SyntaxKind.ExclamationEqualsEqualsToken: + if (isNullOrUndefinedLiteral(expr.right)) { + return narrowTypeByNullCheck(type, expr, assumeTrue); + } + if (expr.left.kind === SyntaxKind.TypeOfExpression && expr.right.kind === SyntaxKind.StringLiteral) { + return narrowTypeByTypeof(type, expr, assumeTrue); + } + break; + case SyntaxKind.AmpersandAmpersandToken: + return narrowTypeByAnd(type, expr, assumeTrue); + case SyntaxKind.BarBarToken: + return narrowTypeByOr(type, expr, assumeTrue); + case SyntaxKind.InstanceOfKeyword: + return narrowTypeByInstanceof(type, expr, assumeTrue); + } + return type; + } + + function narrowTypeByNullCheck(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type { + // We have '==', '!=', '===', or '!==' operator with 'null' or 'undefined' on the right + const operator = expr.operatorToken.kind; + if (operator === SyntaxKind.ExclamationEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken) { + assumeTrue = !assumeTrue; + } + if (!strictNullChecks || !isMatchingReference(expr.left, reference)) { return type; } + const doubleEquals = operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsToken; + const exprNullableKind = doubleEquals ? TypeFlags.Nullable : + expr.right.kind === SyntaxKind.NullKeyword ? TypeFlags.Null : TypeFlags.Undefined; + if (assumeTrue) { + const nullableKind = getNullableKind(type) & exprNullableKind; + return nullableKind ? getNullableTypeOfKind(nullableKind) : type; + } + return removeNullableKind(type, exprNullableKind); + } + + function narrowTypeByTypeof(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type { + // We have '==', '!=', '====', or !==' operator with 'typeof xxx' on the left + // and string literal on the right const left = expr.left; const right = expr.right; - if (left.expression.kind !== SyntaxKind.Identifier || getResolvedSymbol(left.expression) !== symbol) { + if (!isMatchingReference(left.expression, reference)) { return type; } - if (expr.operatorToken.kind === SyntaxKind.ExclamationEqualsEqualsToken) { + if (expr.operatorToken.kind === SyntaxKind.ExclamationEqualsToken || + expr.operatorToken.kind === SyntaxKind.ExclamationEqualsEqualsToken) { assumeTrue = !assumeTrue; } const typeInfo = primitiveTypeInfo[right.text]; @@ -7232,7 +7506,7 @@ namespace ts { function narrowTypeByInstanceof(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type { // Check that type is not any, assumed result is true, and we have variable symbol on the left - if (isTypeAny(type) || expr.left.kind !== SyntaxKind.Identifier || getResolvedSymbol(expr.left) !== symbol) { + if (isTypeAny(type) || !isMatchingReference(expr.left, reference)) { return type; } @@ -7290,7 +7564,8 @@ namespace ts { } } - if (isTypeAssignableTo(narrowedTypeCandidate, originalType)) { + const targetType = originalType.flags & TypeFlags.TypeParameter ? getApparentType(originalType) : originalType; + if (isTypeAssignableTo(narrowedTypeCandidate, targetType)) { // Narrow to the target type if it's assignable to the current type return narrowedTypeCandidate; } @@ -7303,68 +7578,43 @@ namespace ts { return type; } const signature = getResolvedSignature(callExpression); - const predicate = signature.typePredicate; if (!predicate) { return type; } - if (isIdentifierTypePredicate(predicate)) { - if (callExpression.arguments[predicate.parameterIndex] && - getSymbolAtTypePredicatePosition(callExpression.arguments[predicate.parameterIndex]) === symbol) { + const predicateArgument = callExpression.arguments[predicate.parameterIndex]; + if (predicateArgument && isMatchingReference(predicateArgument, reference)) { return getNarrowedType(type, predicate.type, assumeTrue); } } else { const invokedExpression = skipParenthesizedNodes(callExpression.expression); - return narrowTypeByThisTypePredicate(type, predicate, invokedExpression, assumeTrue); - } - return type; - } - - function narrowTypeByThisTypePredicate(type: Type, predicate: ThisTypePredicate, invokedExpression: Expression, assumeTrue: boolean): Type { - if (invokedExpression.kind === SyntaxKind.ElementAccessExpression || invokedExpression.kind === SyntaxKind.PropertyAccessExpression) { - const accessExpression = invokedExpression as ElementAccessExpression | PropertyAccessExpression; - const possibleIdentifier = skipParenthesizedNodes(accessExpression.expression); - if (possibleIdentifier.kind === SyntaxKind.Identifier && getSymbolAtTypePredicatePosition(possibleIdentifier) === symbol) { - return getNarrowedType(type, predicate.type, assumeTrue); + if (invokedExpression.kind === SyntaxKind.ElementAccessExpression || invokedExpression.kind === SyntaxKind.PropertyAccessExpression) { + const accessExpression = invokedExpression as ElementAccessExpression | PropertyAccessExpression; + const possibleReference= skipParenthesizedNodes(accessExpression.expression); + if (isMatchingReference(possibleReference, reference)) { + return getNarrowedType(type, predicate.type, assumeTrue); + } } } return type; } - function getSymbolAtTypePredicatePosition(expr: Expression): Symbol { - expr = skipParenthesizedNodes(expr); - switch (expr.kind) { - case SyntaxKind.Identifier: - case SyntaxKind.PropertyAccessExpression: - return getSymbolOfEntityNameOrPropertyAccessExpression(expr as (Identifier | PropertyAccessExpression)); - } - } - // Narrow the given type based on the given expression having the assumed boolean value. The returned type // will be a subtype or the same type as the argument. function narrowType(type: Type, expr: Expression, assumeTrue: boolean): Type { switch (expr.kind) { + case SyntaxKind.Identifier: + case SyntaxKind.ThisKeyword: + case SyntaxKind.PropertyAccessExpression: + return narrowTypeByTruthiness(type, expr, assumeTrue); case SyntaxKind.CallExpression: return narrowTypeByTypePredicate(type, expr, assumeTrue); case SyntaxKind.ParenthesizedExpression: return narrowType(type, (expr).expression, assumeTrue); case SyntaxKind.BinaryExpression: - const operator = (expr).operatorToken.kind; - if (operator === SyntaxKind.EqualsEqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken) { - return narrowTypeByEquality(type, expr, assumeTrue); - } - else if (operator === SyntaxKind.AmpersandAmpersandToken) { - return narrowTypeByAnd(type, expr, assumeTrue); - } - else if (operator === SyntaxKind.BarBarToken) { - return narrowTypeByOr(type, expr, assumeTrue); - } - else if (operator === SyntaxKind.InstanceOfKeyword) { - return narrowTypeByInstanceof(type, expr, assumeTrue); - } - break; + return narrowTypeByBinaryExpression(type, expr, assumeTrue); case SyntaxKind.PrefixUnaryExpression: if ((expr).operator === SyntaxKind.ExclamationToken) { return narrowType(type, (expr).operand, !assumeTrue); @@ -7375,6 +7625,30 @@ namespace ts { } } + function getTypeOfSymbolAtLocation(symbol: Symbol, location: Node) { + // The language service will always care about the narrowed type of a symbol, because that is + // the type the language says the symbol should have. + const type = getTypeOfSymbol(symbol); + if (location.kind === SyntaxKind.Identifier) { + if (isRightSideOfQualifiedNameOrPropertyAccess(location)) { + location = location.parent; + } + // If location is an identifier or property access that references the given + // symbol, use the location as the reference with respect to which we narrow. + if (isExpression(location)) { + checkExpression(location); + if (getNodeLinks(location).resolvedSymbol === symbol) { + return getNarrowedTypeOfReference(type, location); + } + } + } + // The location isn't a reference to the given symbol, meaning we're being asked + // a hypothetical question of what type the symbol would have if there was a reference + // to it at the given location. To answer that question we manufacture a transient + // identifier at the location and narrow with respect to that identifier. + return getNarrowedTypeOfReference(type, createTransientIdentifier(symbol, location)); + } + function skipParenthesizedNodes(expression: Expression): Expression { while (expression.kind === SyntaxKind.ParenthesizedExpression) { expression = (expression as ParenthesizedExpression).expression; @@ -7382,6 +7656,98 @@ namespace ts { return expression; } + function findFirstAssignment(symbol: Symbol, container: Node): Node { + return visit(isFunctionLike(container) ? (container).body : container); + + function visit(node: Node): Node { + switch (node.kind) { + case SyntaxKind.Identifier: + const assignment = getAssignmentRoot(node); + return assignment && getResolvedSymbol(node) === symbol ? assignment : undefined; + case SyntaxKind.BinaryExpression: + case SyntaxKind.VariableDeclaration: + case SyntaxKind.BindingElement: + case SyntaxKind.ObjectBindingPattern: + case SyntaxKind.ArrayBindingPattern: + case SyntaxKind.ArrayLiteralExpression: + case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ElementAccessExpression: + case SyntaxKind.CallExpression: + case SyntaxKind.NewExpression: + case SyntaxKind.TypeAssertionExpression: + case SyntaxKind.AsExpression: + case SyntaxKind.NonNullExpression: + case SyntaxKind.ParenthesizedExpression: + case SyntaxKind.PrefixUnaryExpression: + case SyntaxKind.DeleteExpression: + case SyntaxKind.AwaitExpression: + case SyntaxKind.TypeOfExpression: + case SyntaxKind.VoidExpression: + case SyntaxKind.PostfixUnaryExpression: + case SyntaxKind.YieldExpression: + case SyntaxKind.ConditionalExpression: + case SyntaxKind.SpreadElementExpression: + case SyntaxKind.VariableStatement: + case SyntaxKind.ExpressionStatement: + case SyntaxKind.IfStatement: + case SyntaxKind.DoStatement: + case SyntaxKind.WhileStatement: + case SyntaxKind.ForStatement: + case SyntaxKind.ForInStatement: + case SyntaxKind.ForOfStatement: + case SyntaxKind.ReturnStatement: + case SyntaxKind.WithStatement: + case SyntaxKind.SwitchStatement: + case SyntaxKind.CaseBlock: + case SyntaxKind.CaseClause: + case SyntaxKind.DefaultClause: + case SyntaxKind.LabeledStatement: + case SyntaxKind.ThrowStatement: + case SyntaxKind.TryStatement: + case SyntaxKind.CatchClause: + case SyntaxKind.JsxElement: + case SyntaxKind.JsxSelfClosingElement: + case SyntaxKind.JsxAttribute: + case SyntaxKind.JsxSpreadAttribute: + case SyntaxKind.JsxOpeningElement: + case SyntaxKind.JsxExpression: + case SyntaxKind.Block: + case SyntaxKind.SourceFile: + return forEachChild(node, visit); + } + return undefined; + } + } + + function checkVariableAssignedBefore(symbol: Symbol, reference: Node) { + if (!(symbol.flags & SymbolFlags.Variable)) { + return; + } + const declaration = symbol.valueDeclaration; + if (!declaration || declaration.kind !== SyntaxKind.VariableDeclaration || (declaration).initializer || isInAmbientContext(declaration)) { + return; + } + const parentParentKind = declaration.parent.parent.kind; + if (parentParentKind === SyntaxKind.ForOfStatement || parentParentKind === SyntaxKind.ForInStatement) { + return; + } + const declarationContainer = getContainingFunction(declaration) || getSourceFileOfNode(declaration); + const referenceContainer = getContainingFunction(reference) || getSourceFileOfNode(reference); + if (declarationContainer !== referenceContainer) { + return; + } + const links = getSymbolLinks(symbol); + if (!links.firstAssignmentChecked) { + links.firstAssignmentChecked = true; + links.firstAssignment = findFirstAssignment(symbol, declarationContainer); + } + if (links.firstAssignment && links.firstAssignment.end <= reference.pos) { + return; + } + error(reference, Diagnostics.Variable_0_is_used_before_being_assigned, symbolToString(symbol)); + } + function checkIdentifier(node: Identifier): Type { const symbol = getResolvedSymbol(node); @@ -7433,7 +7799,11 @@ namespace ts { checkCollisionWithCapturedThisVariable(node, node); checkNestedBlockScopedBinding(node, symbol); - return getNarrowedTypeOfSymbol(localOrExportSymbol, node); + const type = getTypeOfSymbol(localOrExportSymbol); + if (strictNullChecks && !isAssignmentTarget(node) && !(type.flags & TypeFlags.Any) && !(getNullableKind(type) & TypeFlags.Undefined)) { + checkVariableAssignedBefore(symbol, node); + } + return getNarrowedTypeOfReference(type, node); } function isInsideFunction(node: Node, threshold: Node): boolean { @@ -7651,7 +8021,8 @@ namespace ts { if (isClassLike(container.parent)) { const symbol = getSymbolOfNode(container.parent); - return container.flags & NodeFlags.Static ? getTypeOfSymbol(symbol) : (getDeclaredTypeOfSymbol(symbol)).thisType; + const type = container.flags & NodeFlags.Static ? getTypeOfSymbol(symbol) : (getDeclaredTypeOfSymbol(symbol)).thisType; + return getNarrowedTypeOfReference(type, node); } if (isInJavaScriptFile(node)) { @@ -8344,19 +8715,40 @@ namespace ts { return mapper && mapper.context; } + // Return the root assignment node of an assignment target + function getAssignmentRoot(node: Node): Node { + while (node.parent.kind === SyntaxKind.ParenthesizedExpression) { + node = node.parent; + } + while (true) { + if (node.parent.kind === SyntaxKind.PropertyAssignment) { + node = node.parent.parent; + } + else if (node.parent.kind === SyntaxKind.ArrayLiteralExpression) { + node = node.parent; + } + else { + break; + } + } + const parent = node.parent; + return parent.kind === SyntaxKind.BinaryExpression && + (parent).operatorToken.kind === SyntaxKind.EqualsToken && + (parent).left === node ? parent : undefined; + } + // A node is an assignment target if it is on the left hand side of an '=' token, if it is parented by a property // assignment in an object literal that is an assignment target, or if it is parented by an array literal that is // an assignment target. Examples include 'a = xxx', '{ p: a } = xxx', '[{ p: a}] = xxx'. function isAssignmentTarget(node: Node): boolean { + return !!getAssignmentRoot(node); + } + + function isCompoundAssignmentTarget(node: Node) { const parent = node.parent; - if (parent.kind === SyntaxKind.BinaryExpression && (parent).operatorToken.kind === SyntaxKind.EqualsToken && (parent).left === node) { - return true; - } - if (parent.kind === SyntaxKind.PropertyAssignment) { - return isAssignmentTarget(parent.parent); - } - if (parent.kind === SyntaxKind.ArrayLiteralExpression) { - return isAssignmentTarget(parent); + if (parent.kind === SyntaxKind.BinaryExpression && (parent).left === node) { + const operator = (parent).operatorToken.kind; + return operator >= SyntaxKind.FirstAssignment && operator <= SyntaxKind.LastAssignment; } return false; } @@ -8442,7 +8834,7 @@ namespace ts { } } } - return createArrayType(elementTypes.length ? getUnionType(elementTypes) : undefinedType); + return createArrayType(elementTypes.length ? getUnionType(elementTypes) : emptyArrayElementType); } function isNumericName(name: DeclarationName): boolean { @@ -8641,7 +9033,12 @@ namespace ts { checkJsxOpeningLikeElement(node.openingElement); // Perform resolution on the closing tag so that rename/go to definition/etc work - getJsxTagSymbol(node.closingElement); + if (isJsxIntrinsicIdentifier(node.closingElement.tagName)) { + getIntrinsicTagSymbol(node.closingElement); + } + else { + checkExpression(node.closingElement.tagName); + } // Check children for (const child of node.children) { @@ -8751,15 +9148,6 @@ namespace ts { return jsxTypes[name]; } - function getJsxTagSymbol(node: JsxOpeningLikeElement | JsxClosingElement): Symbol { - if (isJsxIntrinsicIdentifier(node.tagName)) { - return getIntrinsicTagSymbol(node); - } - else { - return checkExpression(node.tagName).symbol; - } - } - /** * Looks up an intrinsic tag name and returns a symbol that either points to an intrinsic * property (in which case nodeLinks.jsxFlags will be IntrinsicNamedElement) or an intrinsic @@ -9123,14 +9511,11 @@ namespace ts { } // Property is known to be private or protected at this point - // Get the declaring and enclosing class instance types - const enclosingClassDeclaration = getContainingClass(node); - const enclosingClass = enclosingClassDeclaration ? getDeclaredTypeOfSymbol(getSymbolOfNode(enclosingClassDeclaration)) : undefined; - - // Private property is accessible if declaring and enclosing class are the same + // Private property is accessible if the property is within the declaring class if (flags & NodeFlags.Private) { - if (declaringClass !== enclosingClass) { + const declaringClassDeclaration = getClassLikeDeclarationOfSymbol(getParentOfSymbol(prop)); + if (!isNodeWithinClass(node, declaringClassDeclaration)) { error(errorNode, Diagnostics.Property_0_is_private_and_only_accessible_within_class_1, symbolToString(prop), typeToString(declaringClass)); return false; } @@ -9143,8 +9528,15 @@ namespace ts { if (left.kind === SyntaxKind.SuperKeyword) { return true; } - // A protected property is accessible in the declaring class and classes derived from it - if (!enclosingClass || !hasBaseType(enclosingClass, declaringClass)) { + + // Get the enclosing class that has the declaring class as its base type + const enclosingClass = forEachEnclosingClass(node, enclosingDeclaration => { + const enclosingClass = getDeclaredTypeOfSymbol(getSymbolOfNode(enclosingDeclaration)); + return hasBaseType(enclosingClass, declaringClass) ? enclosingClass : undefined; + }); + + // A protected property is accessible if the property is within the declaring class or classes derived from it + if (!enclosingClass) { error(errorNode, Diagnostics.Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses, symbolToString(prop), typeToString(declaringClass)); return false; } @@ -9166,6 +9558,15 @@ namespace ts { return true; } + function checkNonNullExpression(node: Expression | QualifiedName) { + const type = checkExpression(node); + if (strictNullChecks && getNullableKind(type)) { + error(node, Diagnostics.Object_is_possibly_null_or_undefined); + return getNonNullableType(type); + } + return type; + } + function checkPropertyAccessExpression(node: PropertyAccessExpression) { return checkPropertyAccessExpressionOrQualifiedName(node, node.expression, node.name); } @@ -9175,7 +9576,7 @@ namespace ts { } function checkPropertyAccessExpressionOrQualifiedName(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, right: Identifier) { - const type = checkExpression(left); + const type = checkNonNullExpression(left); if (isTypeAny(type)) { return type; } @@ -9198,7 +9599,10 @@ namespace ts { if (prop.parent && prop.parent.flags & SymbolFlags.Class) { checkClassPropertyAccess(node, left, apparentType, prop); } - return getTypeOfSymbol(prop); + + const propType = getTypeOfSymbol(prop); + return node.kind === SyntaxKind.PropertyAccessExpression && prop.flags & SymbolFlags.Property ? + getNarrowedTypeOfReference(propType, node) : propType; } function isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName, propertyName: string): boolean { @@ -9283,7 +9687,7 @@ namespace ts { } // Obtain base constraint such that we can bail out if the constraint is an unknown type - const objectType = getApparentType(checkExpression(node.expression)); + const objectType = getApparentType(checkNonNullExpression(node.expression)); const indexType = node.argumentExpression ? checkExpression(node.argumentExpression) : unknownType; if (objectType === unknownType) { @@ -10298,7 +10702,7 @@ namespace ts { return resolveUntypedCall(node); } - const funcType = checkExpression(node.expression); + const funcType = checkNonNullExpression(node.expression); const apparentType = getApparentType(funcType); if (apparentType === unknownType) { @@ -10351,7 +10755,7 @@ namespace ts { } } - let expressionType = checkExpression(node.expression); + let expressionType = checkNonNullExpression(node.expression); // If expressionType's apparent type(section 3.8.1) is an object type with one or // more construct signatures, the expression is processed in the same manner as a @@ -10608,21 +11012,32 @@ namespace ts { const targetType = getTypeFromTypeNode(node.type); if (produceDiagnostics && targetType !== unknownType) { const widenedType = getWidenedType(exprType); - - // Permit 'number[] | "foo"' to be asserted to 'string'. - const bothAreStringLike = maybeTypeOfKind(targetType, TypeFlags.StringLike) && - maybeTypeOfKind(widenedType, TypeFlags.StringLike); - if (!bothAreStringLike && !(isTypeAssignableTo(targetType, widenedType))) { - checkTypeAssignableTo(exprType, targetType, node, Diagnostics.Neither_type_0_nor_type_1_is_assignable_to_the_other); + if (!isTypeComparableTo(targetType, widenedType)) { + checkTypeComparableTo(exprType, targetType, node, Diagnostics.Neither_type_0_nor_type_1_is_assignable_to_the_other); } } return targetType; } + function checkNonNullAssertion(node: NonNullExpression) { + return getNonNullableType(checkExpression(node.expression)); + } + + function getTypeOfParameter(symbol: Symbol) { + const type = getTypeOfSymbol(symbol); + if (strictNullChecks) { + const declaration = symbol.valueDeclaration; + if (declaration && (declaration).initializer) { + return addNullableKind(type, TypeFlags.Undefined); + } + } + return type; + } + function getTypeAtPosition(signature: Signature, pos: number): Type { return signature.hasRestParameter ? - pos < signature.parameters.length - 1 ? getTypeOfSymbol(signature.parameters[pos]) : getRestTypeOfSignature(signature) : - pos < signature.parameters.length ? getTypeOfSymbol(signature.parameters[pos]) : anyType; + pos < signature.parameters.length - 1 ? getTypeOfParameter(signature.parameters[pos]) : getRestTypeOfSignature(signature) : + pos < signature.parameters.length ? getTypeOfParameter(signature.parameters[pos]) : anyType; } function assignContextualParameterTypes(signature: Signature, context: Signature, mapper: TypeMapper) { @@ -10748,7 +11163,8 @@ namespace ts { } } else { - types = checkAndAggregateReturnExpressionTypes(func.body, contextualMapper, isAsync); + const hasImplicitReturn = !!(func.flags & NodeFlags.HasImplicitReturn); + types = checkAndAggregateReturnExpressionTypes(func.body, contextualMapper, isAsync, hasImplicitReturn); if (types.length === 0) { if (isAsync) { // For an async function, the return type will not be void, but rather a Promise for void. @@ -10828,9 +11244,9 @@ namespace ts { return aggregatedTypes; } - function checkAndAggregateReturnExpressionTypes(body: Block, contextualMapper?: TypeMapper, isAsync?: boolean): Type[] { + function checkAndAggregateReturnExpressionTypes(body: Block, contextualMapper: TypeMapper, isAsync: boolean, hasImplicitReturn: boolean): Type[] { const aggregatedTypes: Type[] = []; - + let hasOmittedExpressions = false; forEachReturnStatement(body, returnStatement => { const expr = returnStatement.expression; if (expr) { @@ -10842,13 +11258,19 @@ namespace ts { // the native Promise type by the caller. type = checkAwaitedType(type, body.parent, Diagnostics.Return_expression_in_async_function_does_not_have_a_valid_callable_then_member); } - if (!contains(aggregatedTypes, type)) { aggregatedTypes.push(type); } } + else { + hasOmittedExpressions = true; + } }); - + if (strictNullChecks && aggregatedTypes.length && (hasOmittedExpressions || hasImplicitReturn)) { + if (!contains(aggregatedTypes, undefinedType)) { + aggregatedTypes.push(undefinedType); + } + } return aggregatedTypes; } @@ -10885,6 +11307,9 @@ namespace ts { // NOTE: having returnType !== undefined is a precondition for entering this branch so func.type will always be present error(func.type, Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value); } + else if (returnType && strictNullChecks && !isTypeAssignableTo(undefinedType, returnType)) { + error(func.type, Diagnostics.Function_lacks_ending_return_statement_and_return_type_does_not_include_undefined); + } else if (compilerOptions.noImplicitReturns) { if (!returnType) { // If return type annotation is omitted check if function has any explicit return statements. @@ -11132,7 +11557,8 @@ namespace ts { return booleanType; case SyntaxKind.PlusPlusToken: case SyntaxKind.MinusMinusToken: - const ok = checkArithmeticOperandType(node.operand, operandType, Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type); + const ok = checkArithmeticOperandType(node.operand, getNonNullableType(operandType), + Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type); if (ok) { // run check only if former checks succeeded to avoid reporting cascading errors checkReferenceExpression(node.operand, @@ -11146,7 +11572,8 @@ namespace ts { function checkPostfixUnaryExpression(node: PostfixUnaryExpression): Type { const operandType = checkExpression(node.operand); - const ok = checkArithmeticOperandType(node.operand, operandType, Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type); + const ok = checkArithmeticOperandType(node.operand, getNonNullableType(operandType), + Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type); if (ok) { // run check only if former checks succeeded to avoid reporting cascading errors checkReferenceExpression(node.operand, @@ -11397,8 +11824,11 @@ namespace ts { // as having the primitive type Number. If one operand is the null or undefined value, // it is treated as having the type of the other operand. // The result is always of the Number primitive type. - if (leftType.flags & (TypeFlags.Undefined | TypeFlags.Null)) leftType = rightType; - if (rightType.flags & (TypeFlags.Undefined | TypeFlags.Null)) rightType = leftType; + if (leftType.flags & TypeFlags.Nullable) leftType = rightType; + if (rightType.flags & TypeFlags.Nullable) rightType = leftType; + + leftType = getNonNullableType(leftType); + rightType = getNonNullableType(rightType); let suggestedOperator: SyntaxKind; // if a user tries to apply a bitwise operator to 2 boolean operands @@ -11425,8 +11855,11 @@ namespace ts { // or at least one of the operands to be of type Any or the String primitive type. // If one operand is the null or undefined value, it is treated as having the type of the other operand. - if (leftType.flags & (TypeFlags.Undefined | TypeFlags.Null)) leftType = rightType; - if (rightType.flags & (TypeFlags.Undefined | TypeFlags.Null)) rightType = leftType; + if (leftType.flags & TypeFlags.Nullable) leftType = rightType; + if (rightType.flags & TypeFlags.Nullable) rightType = leftType; + + leftType = getNonNullableType(leftType); + rightType = getNonNullableType(rightType); let resultType: Type; if (isTypeOfKind(leftType, TypeFlags.NumberLike) && isTypeOfKind(rightType, TypeFlags.NumberLike)) { @@ -11472,11 +11905,7 @@ namespace ts { case SyntaxKind.ExclamationEqualsToken: case SyntaxKind.EqualsEqualsEqualsToken: case SyntaxKind.ExclamationEqualsEqualsToken: - // Permit 'number[] | "foo"' to be asserted to 'string'. - if (maybeTypeOfKind(leftType, TypeFlags.StringLike) && maybeTypeOfKind(rightType, TypeFlags.StringLike)) { - return booleanType; - } - if (!isTypeAssignableTo(leftType, rightType) && !isTypeAssignableTo(rightType, leftType)) { + if (!isTypeComparableTo(leftType, rightType) && !isTypeComparableTo(rightType, leftType)) { reportOperatorError(); } return booleanType; @@ -11485,9 +11914,9 @@ namespace ts { case SyntaxKind.InKeyword: return checkInExpression(left, right, leftType, rightType); case SyntaxKind.AmpersandAmpersandToken: - return rightType; + return addNullableKind(rightType, getNullableKind(leftType)); case SyntaxKind.BarBarToken: - return getUnionType([leftType, rightType]); + return getUnionType([getNonNullableType(leftType), rightType]); case SyntaxKind.EqualsToken: checkAssignmentOperator(rightType); return getRegularTypeOfObjectLiteral(rightType); @@ -11785,6 +12214,8 @@ namespace ts { case SyntaxKind.TypeAssertionExpression: case SyntaxKind.AsExpression: return checkAssertion(node); + case SyntaxKind.NonNullExpression: + return checkNonNullAssertion(node); case SyntaxKind.DeleteExpression: return checkDeleteExpression(node); case SyntaxKind.VoidExpression: @@ -13654,7 +14085,7 @@ namespace ts { } } - const rightType = checkExpression(node.expression); + const rightType = checkNonNullExpression(node.expression); // unknownType is returned i.e. if node.expression is identifier whose name cannot be resolved // in this case error about missing name is already reported - do not report extra one if (!isTypeAnyOrAllConstituentTypesHaveKind(rightType, TypeFlags.ObjectType | TypeFlags.TypeParameter)) { @@ -13674,7 +14105,7 @@ namespace ts { } function checkRightHandSideOfForOf(rhsExpression: Expression): Type { - const expressionType = getTypeOfExpression(rhsExpression); + const expressionType = checkNonNullExpression(rhsExpression); return checkIteratedTypeOrElementType(expressionType, rhsExpression, /*allowStringInput*/ true); } @@ -13944,8 +14375,8 @@ namespace ts { if (func) { const signature = getSignatureFromDeclaration(func); const returnType = getReturnTypeOfSignature(signature); - if (node.expression) { - const exprType = checkExpressionCached(node.expression); + if (strictNullChecks || node.expression) { + const exprType = node.expression ? checkExpressionCached(node.expression) : undefinedType; if (func.asteriskToken) { // A generator does not need its return expressions checked against its return type. @@ -13956,26 +14387,28 @@ namespace ts { } if (func.kind === SyntaxKind.SetAccessor) { - error(node.expression, Diagnostics.Setters_cannot_return_a_value); + if (node.expression) { + error(node.expression, Diagnostics.Setters_cannot_return_a_value); + } } else if (func.kind === SyntaxKind.Constructor) { - if (!checkTypeAssignableTo(exprType, returnType, node.expression)) { + if (node.expression && !checkTypeAssignableTo(exprType, returnType, node.expression)) { error(node.expression, Diagnostics.Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class); } } else if (func.type || isGetAccessorWithAnnotatedSetAccessor(func)) { if (isAsyncFunctionLike(func)) { const promisedType = getPromisedType(returnType); - const awaitedType = checkAwaitedType(exprType, node.expression, Diagnostics.Return_expression_in_async_function_does_not_have_a_valid_callable_then_member); + const awaitedType = checkAwaitedType(exprType, node.expression || node, Diagnostics.Return_expression_in_async_function_does_not_have_a_valid_callable_then_member); if (promisedType) { // If the function has a return type, but promisedType is // undefined, an error will be reported in checkAsyncFunctionReturnType // so we don't need to report one here. - checkTypeAssignableTo(awaitedType, promisedType, node.expression); + checkTypeAssignableTo(awaitedType, promisedType, node.expression || node); } } else { - checkTypeAssignableTo(exprType, returnType, node.expression); + checkTypeAssignableTo(exprType, returnType, node.expression || node); } } } @@ -14006,7 +14439,6 @@ namespace ts { let hasDuplicateDefaultClause = false; const expressionType = checkExpression(node.expression); - const expressionTypeIsStringLike = maybeTypeOfKind(expressionType, TypeFlags.StringLike); forEach(node.caseBlock.clauses, clause => { // Grammar check for duplicate default clauses, skip if we already report duplicate default clause if (clause.kind === SyntaxKind.DefaultClause && !hasDuplicateDefaultClause) { @@ -14025,17 +14457,12 @@ namespace ts { if (produceDiagnostics && clause.kind === SyntaxKind.CaseClause) { const caseClause = clause; // TypeScript 1.0 spec (April 2014):5.9 - // In a 'switch' statement, each 'case' expression must be of a type that is assignable to or from the type of the 'switch' expression. + // In a 'switch' statement, each 'case' expression must be of a type that is comparable + // to or from the type of the 'switch' expression. const caseType = checkExpression(caseClause.expression); - - const expressionTypeIsAssignableToCaseType = - // Permit 'number[] | "foo"' to be asserted to 'string'. - (expressionTypeIsStringLike && maybeTypeOfKind(caseType, TypeFlags.StringLike)) || - isTypeAssignableTo(expressionType, caseType); - - if (!expressionTypeIsAssignableToCaseType) { - // 'expressionType is not assignable to caseType', try the reversed check and report errors if it fails - checkTypeAssignableTo(caseType, expressionType, caseClause.expression, /*headMessage*/ undefined); + if (!isTypeComparableTo(expressionType, caseType)) { + // expressionType is not comparable to caseType, try the reversed check and report errors if it fails + checkTypeComparableTo(caseType, expressionType, caseClause.expression, /*headMessage*/ undefined); } } forEach(clause.statements, checkSourceElement); @@ -15077,8 +15504,14 @@ namespace ts { const symbol = getSymbolOfNode(node); const target = resolveAlias(symbol); if (target !== unknownSymbol) { + // For external modules symbol represent local symbol for an alias. + // This local symbol will merge any other local declarations (excluding other aliases) + // and symbol.flags will contains combined representation for all merged declaration. + // Based on symbol.flags we can compute a set of excluded meanings (meaning that resolved alias should not have, + // otherwise it will conflict with some local declaration). Note that in addition to normal flags we include matching SymbolFlags.Export* + // in order to prevent collisions with declarations that were exported from the current module (they still contribute to local names). const excludedMeanings = - (symbol.flags & SymbolFlags.Value ? SymbolFlags.Value : 0) | + (symbol.flags & (SymbolFlags.Value | SymbolFlags.ExportValue) ? SymbolFlags.Value : 0) | (symbol.flags & SymbolFlags.Type ? SymbolFlags.Type : 0) | (symbol.flags & SymbolFlags.Namespace ? SymbolFlags.Namespace : 0); if (target.flags & excludedMeanings) { @@ -15689,16 +16122,20 @@ namespace ts { return node.parent && node.parent.kind === SyntaxKind.ExpressionWithTypeArguments; } - function isNodeWithinClass(node: Node, classDeclaration: ClassLikeDeclaration) { + function forEachEnclosingClass(node: Node, callback: (node: Node) => T): T { + let result: T; + while (true) { node = getContainingClass(node); - if (!node) { - return false; - } - if (node === classDeclaration) { - return true; - } + if (!node) break; + if (result = callback(node)) break; } + + return result; + } + + function isNodeWithinClass(node: Node, classDeclaration: ClassLikeDeclaration) { + return !!forEachEnclosingClass(node, n => n === classDeclaration); } function getLeftSideOfImportEqualsOrExportAssignment(nodeOnRightSide: EntityName): ImportEqualsDeclaration | ExportAssignment { @@ -15775,12 +16212,6 @@ namespace ts { meaning |= SymbolFlags.Alias; return resolveEntityName(entityName, meaning); } - else if ((entityName.parent.kind === SyntaxKind.JsxOpeningElement) || - (entityName.parent.kind === SyntaxKind.JsxSelfClosingElement) || - (entityName.parent.kind === SyntaxKind.JsxClosingElement)) { - - return getJsxTagSymbol(entityName.parent); - } else if (isExpression(entityName)) { if (nodeIsMissing(entityName)) { // Missing entity name. @@ -15788,6 +16219,10 @@ namespace ts { } if (entityName.kind === SyntaxKind.Identifier) { + if (isJSXTagName(entityName) && isJsxIntrinsicIdentifier(entityName)) { + return getIntrinsicTagSymbol(entityName.parent); + } + // Include aliases in the meaning, this ensures that we do not follow aliases to where they point and instead // return the alias symbol. const meaning: SymbolFlags = SymbolFlags.Value | SymbolFlags.Alias; diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 5ba54c6553c..f5e96c4a137 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -335,6 +335,11 @@ namespace ts { { name: "disableSizeLimit", type: "boolean" + }, + { + name: "strictNullChecks", + type: "boolean", + description: Diagnostics.Enable_strict_null_checks } ]; @@ -594,9 +599,9 @@ namespace ts { */ export function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions: CompilerOptions = {}, configFileName?: string): ParsedCommandLine { const errors: Diagnostic[] = []; - const compilerOptions: CompilerOptions = convertCompilerOptionsFromJson(optionDeclarations, json["compilerOptions"], basePath, errors, configFileName); + const compilerOptions: CompilerOptions = convertCompilerOptionsFromJsonWorker(json["compilerOptions"], basePath, errors, configFileName); const options = extend(existingOptions, compilerOptions); - const typingOptions: TypingOptions = convertTypingOptionsFromJson(typingOptionDeclarations, json["typingOptions"], basePath, errors, configFileName); + const typingOptions: TypingOptions = convertTypingOptionsFromJsonWorker(json["typingOptions"], basePath, errors, configFileName); const fileNames = getFileNames(errors); @@ -684,28 +689,38 @@ namespace ts { } } - /* @internal */ - export function convertCompilerOptionsFromJson(optionsDeclarations: CommandLineOption[], jsonOptions: any, + export function convertCompilerOptionsFromJson(jsonOptions: any, basePath: string, configFileName?: string): { options: CompilerOptions, errors: Diagnostic[] } { + const errors: Diagnostic[] = []; + const options = convertCompilerOptionsFromJsonWorker(jsonOptions, basePath, errors, configFileName); + return { options, errors }; + } + + export function convertTypingOptionsFromJson(jsonOptions: any, basePath: string, configFileName?: string): { options: CompilerOptions, errors: Diagnostic[] } { + const errors: Diagnostic[] = []; + const options = convertTypingOptionsFromJsonWorker(jsonOptions, basePath, errors, configFileName); + return { options, errors }; + } + + function convertCompilerOptionsFromJsonWorker(jsonOptions: any, basePath: string, errors: Diagnostic[], configFileName?: string): CompilerOptions { const options: CompilerOptions = getBaseFileName(configFileName) === "jsconfig.json" ? { allowJs: true } : {}; - convertOptionsFromJson(optionDeclarations, jsonOptions, basePath, options, Diagnostics.Unknown_compiler_option_0, errors); + convertOptionsFromJson(optionDeclarations, jsonOptions, basePath, options, Diagnostics.Unknown_compiler_option_0, errors); return options; } - /* @internal */ - export function convertTypingOptionsFromJson(optionsDeclarations: CommandLineOption[], jsonOptions: any, + function convertTypingOptionsFromJsonWorker(jsonOptions: any, basePath: string, errors: Diagnostic[], configFileName?: string): TypingOptions { const options: TypingOptions = getBaseFileName(configFileName) === "jsconfig.json" ? { enableAutoDiscovery: true, include: [], exclude: [] } : { enableAutoDiscovery: false, include: [], exclude: [] }; - convertOptionsFromJson(typingOptionDeclarations, jsonOptions, basePath, options, Diagnostics.Unknown_typing_option_0, errors); + convertOptionsFromJson(typingOptionDeclarations, jsonOptions, basePath, options, Diagnostics.Unknown_typing_option_0, errors); return options; } - function convertOptionsFromJson(optionDeclarations: CommandLineOption[], jsonOptions: any, basePath: string, - defaultOptions: T, diagnosticMessage: DiagnosticMessage, errors: Diagnostic[]) { + function convertOptionsFromJson(optionDeclarations: CommandLineOption[], jsonOptions: any, basePath: string, + defaultOptions: CompilerOptions | TypingOptions, diagnosticMessage: DiagnosticMessage, errors: Diagnostic[]) { if (!jsonOptions) { return ; diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 93286db7e46..76306e290ca 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -242,8 +242,14 @@ namespace ts { const count = array.length; if (count > 0) { let pos = 0; - let result = arguments.length <= 2 ? array[pos] : initial; - pos++; + let result: T | U; + if (arguments.length <= 2) { + result = array[pos]; + pos++; + } + else { + result = initial; + } while (pos < count) { result = f(result, array[pos]); pos++; @@ -260,8 +266,14 @@ namespace ts { if (array) { let pos = array.length - 1; if (pos >= 0) { - let result = arguments.length <= 2 ? array[pos] : initial; - pos--; + let result: T | U; + if (arguments.length <= 2) { + result = array[pos]; + pos--; + } + else { + result = initial; + } while (pos >= 0) { result = f(result, array[pos]); pos--; diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index c758d658888..0a8b6615a23 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -367,6 +367,8 @@ namespace ts { case SyntaxKind.BooleanKeyword: case SyntaxKind.SymbolKeyword: case SyntaxKind.VoidKeyword: + case SyntaxKind.UndefinedKeyword: + case SyntaxKind.NullKeyword: case SyntaxKind.ThisType: case SyntaxKind.StringLiteralType: return writeTextOfNode(currentText, type); diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index cdbd1a6ebee..6b6b7ee3d2b 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1103,6 +1103,10 @@ "category": "Error", "code": 2365 }, + "Function lacks ending return statement and return type does not include 'undefined'.": { + "category": "Error", + "code": 2366 + }, "Type parameter name cannot be '{0}'": { "category": "Error", "code": 2368 @@ -1423,6 +1427,10 @@ "category": "Error", "code": 2453 }, + "Variable '{0}' is used before being assigned.": { + "category": "Error", + "code": 2454 + }, "Type argument candidate '{1}' is not a valid type argument because it is not a supertype of candidate '{0}'.": { "category": "Error", "code": 2455 @@ -1719,6 +1727,10 @@ "category": "Error", "code": 2530 }, + "Object is possibly 'null' or 'undefined'.": { + "category": "Error", + "code": 2531 + }, "JSX element attributes type '{0}' may not be a union type.": { "category": "Error", "code": 2600 @@ -2604,6 +2616,11 @@ "category": "Message", "code": 6112 }, + "Enable strict null checks.": { + "category": "Message", + "code": 6113 + }, + "Variable '{0}' implicitly has an '{1}' type.": { "category": "Error", "code": 7005 diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 8e474546ec9..0cb28a72a67 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1533,6 +1533,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge case SyntaxKind.JsxSpreadAttribute: case SyntaxKind.JsxExpression: case SyntaxKind.NewExpression: + case SyntaxKind.NonNullExpression: case SyntaxKind.ParenthesizedExpression: case SyntaxKind.PostfixUnaryExpression: case SyntaxKind.PrefixUnaryExpression: @@ -2077,8 +2078,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge function parenthesizeForAccess(expr: Expression): LeftHandSideExpression { // When diagnosing whether the expression needs parentheses, the decision should be based // on the innermost expression in a chain of nested type assertions. - while (expr.kind === SyntaxKind.TypeAssertionExpression || expr.kind === SyntaxKind.AsExpression) { - expr = (expr).expression; + while (expr.kind === SyntaxKind.TypeAssertionExpression || + expr.kind === SyntaxKind.AsExpression || + expr.kind === SyntaxKind.NonNullExpression) { + expr = (expr).expression; } // isLeftHandSideExpression is almost the correct criterion for when it is not necessary @@ -2343,8 +2346,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge } function skipParentheses(node: Expression): Expression { - while (node.kind === SyntaxKind.ParenthesizedExpression || node.kind === SyntaxKind.TypeAssertionExpression || node.kind === SyntaxKind.AsExpression) { - node = (node).expression; + while (node.kind === SyntaxKind.ParenthesizedExpression || + node.kind === SyntaxKind.TypeAssertionExpression || + node.kind === SyntaxKind.AsExpression || + node.kind === SyntaxKind.NonNullExpression) { + node = (node).expression; } return node; } @@ -2518,13 +2524,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge // not the user. If we didn't want them, the emitter would not have put them // there. if (!nodeIsSynthesized(node) && node.parent.kind !== SyntaxKind.ArrowFunction) { - if (node.expression.kind === SyntaxKind.TypeAssertionExpression || node.expression.kind === SyntaxKind.AsExpression) { - let operand = (node.expression).expression; + if (node.expression.kind === SyntaxKind.TypeAssertionExpression || + node.expression.kind === SyntaxKind.AsExpression || + node.expression.kind === SyntaxKind.NonNullExpression) { + let operand = (node.expression).expression; // Make sure we consider all nested cast expressions, e.g.: // (-A).x; - while (operand.kind === SyntaxKind.TypeAssertionExpression || operand.kind === SyntaxKind.AsExpression) { - operand = (operand).expression; + while (operand.kind === SyntaxKind.TypeAssertionExpression || + operand.kind === SyntaxKind.AsExpression || + operand.kind === SyntaxKind.NonNullExpression) { + operand = (operand).expression; } // We have an expression of the form: (SubExpr) @@ -7928,9 +7938,9 @@ const _super = (function (geti, seti) { case SyntaxKind.TaggedTemplateExpression: return emitTaggedTemplateExpression(node); case SyntaxKind.TypeAssertionExpression: - return emit((node).expression); case SyntaxKind.AsExpression: - return emit((node).expression); + case SyntaxKind.NonNullExpression: + return emit((node).expression); case SyntaxKind.ParenthesizedExpression: return emitParenExpression(node); case SyntaxKind.FunctionDeclaration: diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 4f8d2469110..b7c011631ee 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -177,6 +177,8 @@ namespace ts { case SyntaxKind.AsExpression: return visitNode(cbNode, (node).expression) || visitNode(cbNode, (node).type); + case SyntaxKind.NonNullExpression: + return visitNode(cbNode, (node).expression); case SyntaxKind.ConditionalExpression: return visitNode(cbNode, (node).condition) || visitNode(cbNode, (node).questionToken) || @@ -2361,12 +2363,14 @@ namespace ts { case SyntaxKind.NumberKeyword: case SyntaxKind.BooleanKeyword: case SyntaxKind.SymbolKeyword: + case SyntaxKind.UndefinedKeyword: // If these are followed by a dot, then parse these out as a dotted type reference instead. const node = tryParse(parseKeywordAndNoDot); return node || parseTypeReference(); case SyntaxKind.StringLiteral: return parseStringLiteralTypeNode(); case SyntaxKind.VoidKeyword: + case SyntaxKind.NullKeyword: return parseTokenNode(); case SyntaxKind.ThisKeyword: { const thisKeyword = parseThisTypeNode(); @@ -2398,6 +2402,8 @@ namespace ts { case SyntaxKind.BooleanKeyword: case SyntaxKind.SymbolKeyword: case SyntaxKind.VoidKeyword: + case SyntaxKind.UndefinedKeyword: + case SyntaxKind.NullKeyword: case SyntaxKind.ThisKeyword: case SyntaxKind.TypeOfKeyword: case SyntaxKind.OpenBraceToken: @@ -3724,6 +3730,14 @@ namespace ts { continue; } + if (token === SyntaxKind.ExclamationToken && !scanner.hasPrecedingLineBreak()) { + nextToken(); + const nonNullExpression = createNode(SyntaxKind.NonNullExpression, expression.pos); + nonNullExpression.expression = expression; + expression = finishNode(nonNullExpression); + continue; + } + // when in the [Decorator] context, we do not parse ElementAccess as it could be part of a ComputedPropertyName if (!inDecoratorContext() && parseOptional(SyntaxKind.OpenBracketToken)) { const indexedAccess = createNode(SyntaxKind.ElementAccessExpression, expression.pos); diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 64747fc638c..8979814a7a2 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -114,6 +114,7 @@ namespace ts { "try": SyntaxKind.TryKeyword, "type": SyntaxKind.TypeKeyword, "typeof": SyntaxKind.TypeOfKeyword, + "undefined": SyntaxKind.UndefinedKeyword, "var": SyntaxKind.VarKeyword, "void": SyntaxKind.VoidKeyword, "while": SyntaxKind.WhileKeyword, diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 3638cc3a92f..9905ce54c74 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -171,6 +171,7 @@ namespace ts { StringKeyword, SymbolKeyword, TypeKeyword, + UndefinedKeyword, FromKeyword, GlobalKeyword, OfKeyword, // LastKeyword and LastToken @@ -240,6 +241,7 @@ namespace ts { OmittedExpression, ExpressionWithTypeArguments, AsExpression, + NonNullExpression, // Misc TemplateSpan, @@ -475,6 +477,11 @@ namespace ts { originalKeywordKind?: SyntaxKind; // Original syntaxKind which get set so that we can report an error later } + // Transient identifier node (marked by id === -1) + export interface TransientIdentifier extends Identifier { + resolvedSymbol: Symbol; + } + // @kind(SyntaxKind.QualifiedName) export interface QualifiedName extends Node { // Must have same layout as PropertyAccess @@ -968,6 +975,8 @@ namespace ts { name: Identifier; } + export type IdentifierOrPropertyAccess = Identifier | PropertyAccessExpression; + // @kind(SyntaxKind.ElementAccessExpression) export interface ElementAccessExpression extends MemberExpression { expression: LeftHandSideExpression; @@ -1012,6 +1021,11 @@ namespace ts { export type AssertionExpression = TypeAssertion | AsExpression; + // @kind(SyntaxKind.NonNullExpression) + export interface NonNullExpression extends LeftHandSideExpression { + expression: Expression; + } + /// A JSX expression of the form ... // @kind(SyntaxKind.JsxElement) export interface JsxElement extends PrimaryExpression { @@ -2030,7 +2044,9 @@ namespace ts { exportsChecked?: boolean; // True if exports of external module have been checked isDeclarationWithCollidingName?: boolean; // True if symbol is block scoped redeclaration bindingElement?: BindingElement; // Binding element associated with property symbol - exportsSomeValue?: boolean; // true if module exports some value (not just types) + exportsSomeValue?: boolean; // True if module exports some value (not just types) + firstAssignmentChecked?: boolean; // True if first assignment node has been computed + firstAssignment?: Node; // First assignment node (undefined if no assignments) } /* @internal */ @@ -2073,7 +2089,7 @@ namespace ts { isVisible?: boolean; // Is this node visible generatedName?: string; // Generated name for module, enum, or import declaration generatedNames?: Map; // Generated names table for source file - assignmentChecks?: Map; // Cache of assignment checks + assignmentMap?: Map; // Cached map of references assigned within this node hasReportedStatementInAmbientContext?: boolean; // Cache boolean if we report statements in ambient context importOnRightSide?: Symbol; // for import declarations - import that appear on the right side jsxFlags?: JsxFlags; // flags for knowing what kind of element/attributes we're dealing with @@ -2107,7 +2123,7 @@ namespace ts { /* @internal */ FreshObjectLiteral = 0x00100000, // Fresh object literal type /* @internal */ - ContainsUndefinedOrNull = 0x00200000, // Type is or contains Undefined or Null type + ContainsUndefinedOrNull = 0x00200000, // Type is or contains undefined or null type /* @internal */ ContainsObjectLiteral = 0x00400000, // Type is or contains object literal type /* @internal */ @@ -2116,6 +2132,8 @@ namespace ts { ThisType = 0x02000000, // This type ObjectLiteralPatternWithComputedProperties = 0x04000000, // Object literal type implied by binding pattern has computed properties + /* @internal */ + Nullable = Undefined | Null, /* @internal */ Intrinsic = Any | String | Number | Boolean | ESSymbol | Void | Undefined | Null, /* @internal */ @@ -2440,6 +2458,7 @@ namespace ts { allowSyntheticDefaultImports?: boolean; allowJs?: boolean; noImplicitUseStrict?: boolean; + strictNullChecks?: boolean; disableSizeLimit?: boolean; lib?: string[]; /* @internal */ stripInternal?: boolean; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 6520e339ac9..fbec5af2176 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -511,6 +511,7 @@ namespace ts { case SyntaxKind.StringKeyword: case SyntaxKind.BooleanKeyword: case SyntaxKind.SymbolKeyword: + case SyntaxKind.UndefinedKeyword: return true; case SyntaxKind.VoidKeyword: return node.parent.kind !== SyntaxKind.VoidExpression; @@ -952,6 +953,16 @@ namespace ts { return node.kind === SyntaxKind.ElementAccessExpression; } + export function isJSXTagName(node: Node) { + const parent = node.parent; + if (parent.kind === SyntaxKind.JsxOpeningElement || + parent.kind === SyntaxKind.JsxSelfClosingElement || + parent.kind === SyntaxKind.JsxClosingElement) { + return (parent).tagName === node; + } + return false; + } + export function isExpression(node: Node): boolean { switch (node.kind) { case SyntaxKind.SuperKeyword: @@ -968,6 +979,7 @@ namespace ts { case SyntaxKind.TaggedTemplateExpression: case SyntaxKind.AsExpression: case SyntaxKind.TypeAssertionExpression: + case SyntaxKind.NonNullExpression: case SyntaxKind.ParenthesizedExpression: case SyntaxKind.FunctionExpression: case SyntaxKind.ClassExpression: @@ -992,9 +1004,9 @@ namespace ts { while (node.parent.kind === SyntaxKind.QualifiedName) { node = node.parent; } - return node.parent.kind === SyntaxKind.TypeQuery; + return node.parent.kind === SyntaxKind.TypeQuery || isJSXTagName(node); case SyntaxKind.Identifier: - if (node.parent.kind === SyntaxKind.TypeQuery) { + if (node.parent.kind === SyntaxKind.TypeQuery || isJSXTagName(node)) { return true; } // fall through @@ -2406,6 +2418,7 @@ namespace ts { case SyntaxKind.ElementAccessExpression: case SyntaxKind.NewExpression: case SyntaxKind.CallExpression: + case SyntaxKind.NonNullExpression: case SyntaxKind.JsxElement: case SyntaxKind.JsxSelfClosingElement: case SyntaxKind.TaggedTemplateExpression: diff --git a/src/lib/core.d.ts b/src/lib/core.d.ts index cc30bdd4adb..e3f5928794f 100644 --- a/src/lib/core.d.ts +++ b/src/lib/core.d.ts @@ -304,13 +304,13 @@ interface String { * Matches a string with a regular expression, and returns an array containing the results of that search. * @param regexp A variable name or string literal containing the regular expression pattern and flags. */ - match(regexp: string): RegExpMatchArray; + match(regexp: string): RegExpMatchArray | null; /** * Matches a string with a regular expression, and returns an array containing the results of that search. * @param regexp A regular expression object that contains the regular expression pattern and applicable flags. */ - match(regexp: RegExp): RegExpMatchArray; + match(regexp: RegExp): RegExpMatchArray | null; /** * Replaces text in a string, using a regular expression or search string. @@ -813,7 +813,7 @@ interface RegExp { * Executes a search on a string using a regular expression pattern, and returns an array containing the results of that search. * @param string The String object or string literal on which to perform the search. */ - exec(string: string): RegExpExecArray; + exec(string: string): RegExpExecArray | null; /** * Returns a Boolean value that indicates whether or not a pattern exists in a searched string. @@ -836,7 +836,7 @@ interface RegExp { lastIndex: number; // Non-standard extensions - compile(): RegExp; + compile(): this; } interface RegExpConstructor { @@ -1108,7 +1108,7 @@ interface Array { /** * Removes the last element from an array and returns it. */ - pop(): T; + pop(): T | undefined; /** * Combines two or more arrays. * @param items Additional items to add to the end of array1. @@ -1126,7 +1126,7 @@ interface Array { /** * Removes the first element from an array and returns it. */ - shift(): T; + shift(): T | undefined; /** * Returns a section of an array. * @param start The beginning of the specified portion of the array. @@ -1519,7 +1519,7 @@ interface Int8Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; + find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** * Returns the index of the first element in the array where predicate is true, and undefined @@ -1530,7 +1530,7 @@ interface Int8Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: number) => boolean, thisArg?: any): number; + findIndex(predicate: (value: number) => boolean, thisArg?: any): number | undefined; /** * Performs the specified action for each element in an array. @@ -1792,7 +1792,7 @@ interface Uint8Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; + find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** * Returns the index of the first element in the array where predicate is true, and undefined @@ -1803,7 +1803,7 @@ interface Uint8Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: number) => boolean, thisArg?: any): number; + findIndex(predicate: (value: number) => boolean, thisArg?: any): number | undefined; /** * Performs the specified action for each element in an array. @@ -2066,7 +2066,7 @@ interface Uint8ClampedArray { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; + find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** * Returns the index of the first element in the array where predicate is true, and undefined @@ -2077,7 +2077,7 @@ interface Uint8ClampedArray { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: number) => boolean, thisArg?: any): number; + findIndex(predicate: (value: number) => boolean, thisArg?: any): number | undefined; /** * Performs the specified action for each element in an array. @@ -2339,7 +2339,7 @@ interface Int16Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; + find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** * Returns the index of the first element in the array where predicate is true, and undefined @@ -2350,7 +2350,7 @@ interface Int16Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: number) => boolean, thisArg?: any): number; + findIndex(predicate: (value: number) => boolean, thisArg?: any): number | undefined; /** * Performs the specified action for each element in an array. @@ -2613,7 +2613,7 @@ interface Uint16Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; + find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** * Returns the index of the first element in the array where predicate is true, and undefined @@ -2624,7 +2624,7 @@ interface Uint16Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: number) => boolean, thisArg?: any): number; + findIndex(predicate: (value: number) => boolean, thisArg?: any): number | undefined; /** * Performs the specified action for each element in an array. @@ -2886,7 +2886,7 @@ interface Int32Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; + find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** * Returns the index of the first element in the array where predicate is true, and undefined @@ -2897,7 +2897,7 @@ interface Int32Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: number) => boolean, thisArg?: any): number; + findIndex(predicate: (value: number) => boolean, thisArg?: any): number | undefined; /** * Performs the specified action for each element in an array. @@ -3159,7 +3159,7 @@ interface Uint32Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; + find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** * Returns the index of the first element in the array where predicate is true, and undefined @@ -3170,7 +3170,7 @@ interface Uint32Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: number) => boolean, thisArg?: any): number; + findIndex(predicate: (value: number) => boolean, thisArg?: any): number | undefined; /** * Performs the specified action for each element in an array. @@ -3432,7 +3432,7 @@ interface Float32Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; + find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** * Returns the index of the first element in the array where predicate is true, and undefined @@ -3443,7 +3443,7 @@ interface Float32Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: number) => boolean, thisArg?: any): number; + findIndex(predicate: (value: number) => boolean, thisArg?: any): number | undefined; /** * Performs the specified action for each element in an array. @@ -3706,7 +3706,7 @@ interface Float64Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; + find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** * Returns the index of the first element in the array where predicate is true, and undefined @@ -3717,7 +3717,7 @@ interface Float64Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: number) => boolean, thisArg?: any): number; + findIndex(predicate: (value: number) => boolean, thisArg?: any): number | undefined; /** * Performs the specified action for each element in an array. diff --git a/src/lib/es6.d.ts b/src/lib/es6.d.ts index 5a0812aad77..40984ab1512 100644 --- a/src/lib/es6.d.ts +++ b/src/lib/es6.d.ts @@ -34,7 +34,7 @@ interface SymbolConstructor { * Otherwise, returns a undefined. * @param sym Symbol to find the key for. */ - keyFor(sym: symbol): string; + keyFor(sym: symbol): string | undefined; // Well-known Symbols @@ -320,7 +320,7 @@ interface Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - find(predicate: (value: T, index: number, obj: Array) => boolean, thisArg?: any): T; + find(predicate: (value: T, index: number, obj: Array) => boolean, thisArg?: any): T | undefined; /** * Returns the index of the first element in the array where predicate is true, and undefined @@ -331,7 +331,7 @@ interface Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: T) => boolean, thisArg?: any): number; + findIndex(predicate: (value: T) => boolean, thisArg?: any): number | undefined; /** * Returns the this object after filling the section identified by start and end with value @@ -407,7 +407,7 @@ interface String { * If there is no element at that position, the result is undefined. * If a valid UTF-16 surrogate pair does not begin at pos, the result is the code unit at pos. */ - codePointAt(pos: number): number; + codePointAt(pos: number): number | undefined; /** * Returns true if searchString appears as a substring of the result of converting this @@ -453,7 +453,7 @@ interface String { * Matches a string an object that supports being matched against, and returns an array containing the results of that search. * @param matcher An object that supports being matched against. */ - match(matcher: { [Symbol.match](string: string): RegExpMatchArray; }): RegExpMatchArray; + match(matcher: { [Symbol.match](string: string): RegExpMatchArray | null; }): RegExpMatchArray | null; /** * Replaces text in a string, using an object that supports replacement within a string. @@ -723,7 +723,7 @@ interface RegExp { * that search. * @param string A string to search within. */ - [Symbol.match](string: string): RegExpMatchArray; + [Symbol.match](string: string): RegExpMatchArray | null; /** * Replaces text in a string, using this regular expression. @@ -800,7 +800,7 @@ interface Map { delete(key: K): boolean; entries(): IterableIterator<[K, V]>; forEach(callbackfn: (value: V, index: K, map: Map) => void, thisArg?: any): void; - get(key: K): V; + get(key: K): V | undefined; has(key: K): boolean; keys(): IterableIterator; set(key: K, value?: V): Map; @@ -821,7 +821,7 @@ declare var Map: MapConstructor; interface WeakMap { clear(): void; delete(key: K): boolean; - get(key: K): V; + get(key: K): V | undefined; has(key: K): boolean; set(key: K, value?: V): WeakMap; readonly [Symbol.toStringTag]: "WeakMap"; diff --git a/tests/baselines/reference/APISample_parseConfig.js b/tests/baselines/reference/APISample_parseConfig.js new file mode 100644 index 00000000000..1312f8a4f81 --- /dev/null +++ b/tests/baselines/reference/APISample_parseConfig.js @@ -0,0 +1,70 @@ +//// [APISample_parseConfig.ts] + +/* + * Note: This test is a public API sample. The sample sources can be found + at: https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#a-minimal-compiler + * Please log a "breaking change" issue for any API breaking change affecting this issue + */ + +declare var process: any; +declare var console: any; +declare var os: any; + +import ts = require("typescript"); + +function printError(error: ts.Diagnostic): void { + if (!error) { + return; + } + console.log(`${error.file && error.file.fileName}: ${error.messageText}`); +} + +export function createProgram(rootFiles: string[], compilerOptionsJson: string): ts.Program { + const { config, error } = ts.parseConfigFileTextToJson("tsconfig.json", compilerOptionsJson) + if (error) { + printError(error); + return undefined; + } + const basePath: string = process.cwd(); + const settings = ts.convertCompilerOptionsFromJson(config.config["compilerOptions"], basePath); + if (!settings.options) { + for (const err of settings.errors) { + printError(err); + } + return undefined; + } + return ts.createProgram(rootFiles, settings.options); +} + +//// [APISample_parseConfig.js] +/* + * Note: This test is a public API sample. The sample sources can be found + at: https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#a-minimal-compiler + * Please log a "breaking change" issue for any API breaking change affecting this issue + */ +"use strict"; +var ts = require("typescript"); +function printError(error) { + if (!error) { + return; + } + console.log((error.file && error.file.fileName) + ": " + error.messageText); +} +function createProgram(rootFiles, compilerOptionsJson) { + var _a = ts.parseConfigFileTextToJson("tsconfig.json", compilerOptionsJson), config = _a.config, error = _a.error; + if (error) { + printError(error); + return undefined; + } + var basePath = process.cwd(); + var settings = ts.convertCompilerOptionsFromJson(config.config["compilerOptions"], basePath); + if (!settings.options) { + for (var _i = 0, _b = settings.errors; _i < _b.length; _i++) { + var err = _b[_i]; + printError(err); + } + return undefined; + } + return ts.createProgram(rootFiles, settings.options); +} +exports.createProgram = createProgram; diff --git a/tests/baselines/reference/arrayLiteralWidened.types b/tests/baselines/reference/arrayLiteralWidened.types index 9599db2dff5..83db7046eed 100644 --- a/tests/baselines/reference/arrayLiteralWidened.types +++ b/tests/baselines/reference/arrayLiteralWidened.types @@ -19,7 +19,7 @@ var a = [undefined, undefined]; var b = [[], [null, null]]; // any[][] >b : any[][] ->[[], [null, null]] : null[][] +>[[], [null, null]] : undefined[][] >[] : undefined[] >[null, null] : null[] >null : null diff --git a/tests/baselines/reference/castingTuple.errors.txt b/tests/baselines/reference/castingTuple.errors.txt index 62a36c9c156..128ee5b5bb4 100644 --- a/tests/baselines/reference/castingTuple.errors.txt +++ b/tests/baselines/reference/castingTuple.errors.txt @@ -1,7 +1,3 @@ -tests/cases/conformance/types/tuple/castingTuple.ts(13,23): error TS2352: Neither type '[number, string]' nor type '[number, string, boolean]' is assignable to the other. - Property '2' is missing in type '[number, string]'. -tests/cases/conformance/types/tuple/castingTuple.ts(16,21): error TS2352: Neither type '[C, D]' nor type '[C, D, A]' is assignable to the other. - Property '2' is missing in type '[C, D]'. tests/cases/conformance/types/tuple/castingTuple.ts(28,10): error TS2352: Neither type '[number, string]' nor type '[number, number]' is assignable to the other. Types of property '1' are incompatible. Type 'string' is not assignable to type 'number'. @@ -10,15 +6,10 @@ tests/cases/conformance/types/tuple/castingTuple.ts(29,10): error TS2352: Neithe Type 'C' is not assignable to type 'A'. Property 'a' is missing in type 'C'. tests/cases/conformance/types/tuple/castingTuple.ts(30,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'array1' must be of type '{}[]', but here has type 'number[]'. -tests/cases/conformance/types/tuple/castingTuple.ts(30,14): error TS2352: Neither type '[number, string]' nor type 'number[]' is assignable to the other. - Types of property 'pop' are incompatible. - Type '() => number | string' is not assignable to type '() => number'. - Type 'number | string' is not assignable to type 'number'. - Type 'string' is not assignable to type 'number'. tests/cases/conformance/types/tuple/castingTuple.ts(31,1): error TS2304: Cannot find name 't4'. -==== tests/cases/conformance/types/tuple/castingTuple.ts (7 errors) ==== +==== tests/cases/conformance/types/tuple/castingTuple.ts (4 errors) ==== interface I { } class A { a = 10; } class C implements I { c }; @@ -32,15 +23,9 @@ tests/cases/conformance/types/tuple/castingTuple.ts(31,1): error TS2304: Cannot var numStrTuple: [number, string] = [5, "foo"]; var emptyObjTuple = <[{}, {}]>numStrTuple; var numStrBoolTuple = <[number, string, boolean]>numStrTuple; - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2352: Neither type '[number, string]' nor type '[number, string, boolean]' is assignable to the other. -!!! error TS2352: Property '2' is missing in type '[number, string]'. var classCDTuple: [C, D] = [new C(), new D()]; var interfaceIITuple = <[I, I]>classCDTuple; var classCDATuple = <[C, D, A]>classCDTuple; - ~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2352: Neither type '[C, D]' nor type '[C, D, A]' is assignable to the other. -!!! error TS2352: Property '2' is missing in type '[C, D]'. var eleFromCDA1 = classCDATuple[2]; // A var eleFromCDA2 = classCDATuple[5]; // C | D | A var t10: [E1, E2] = [E1.one, E2.one]; @@ -66,12 +51,6 @@ tests/cases/conformance/types/tuple/castingTuple.ts(31,1): error TS2304: Cannot var array1 = numStrTuple; ~~~~~~ !!! error TS2403: Subsequent variable declarations must have the same type. Variable 'array1' must be of type '{}[]', but here has type 'number[]'. - ~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2352: Neither type '[number, string]' nor type 'number[]' is assignable to the other. -!!! error TS2352: Types of property 'pop' are incompatible. -!!! error TS2352: Type '() => number | string' is not assignable to type '() => number'. -!!! error TS2352: Type 'number | string' is not assignable to type 'number'. -!!! error TS2352: Type 'string' is not assignable to type 'number'. t4[2] = 10; ~~ !!! error TS2304: Cannot find name 't4'. diff --git a/tests/baselines/reference/contextualTypeWithTuple.errors.txt b/tests/baselines/reference/contextualTypeWithTuple.errors.txt index e447ed62b39..a2d3b224ddc 100644 --- a/tests/baselines/reference/contextualTypeWithTuple.errors.txt +++ b/tests/baselines/reference/contextualTypeWithTuple.errors.txt @@ -3,7 +3,6 @@ tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(3,5): error TS232 Type '() => number | string | boolean' is not assignable to type '() => number | string'. Type 'number | string | boolean' is not assignable to type 'number | string'. Type 'boolean' is not assignable to type 'number | string'. - Type 'boolean' is not assignable to type 'string'. tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(15,1): error TS2322: Type '[number, string, boolean]' is not assignable to type '[number, string]'. tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(18,1): error TS2322: Type '[{}, number]' is not assignable to type '[{ a: string; }, number]'. Types of property '0' are incompatible. @@ -34,7 +33,6 @@ tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(25,1): error TS23 !!! error TS2322: Type '() => number | string | boolean' is not assignable to type '() => number | string'. !!! error TS2322: Type 'number | string | boolean' is not assignable to type 'number | string'. !!! error TS2322: Type 'boolean' is not assignable to type 'number | string'. -!!! error TS2322: Type 'boolean' is not assignable to type 'string'. var numStrBoolTuple: [number, string, boolean] = [5, "foo", true]; var objNumTuple: [{ a: string }, number] = [{ a: "world" }, 5]; var strTupleTuple: [string, [number, {}]] = ["bar", [5, { x: 1, y: 1 }]]; diff --git a/tests/baselines/reference/contextuallyTypedBindingInitializerNegative.errors.txt b/tests/baselines/reference/contextuallyTypedBindingInitializerNegative.errors.txt index 689645386c4..42d617887e0 100644 --- a/tests/baselines/reference/contextuallyTypedBindingInitializerNegative.errors.txt +++ b/tests/baselines/reference/contextuallyTypedBindingInitializerNegative.errors.txt @@ -14,7 +14,6 @@ tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTyp Types of property '0' are incompatible. Type 'number' is not assignable to type 'string'. tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(26,14): error TS2322: Type '"baz"' is not assignable to type '"foo" | "bar"'. - Type '"baz"' is not assignable to type '"bar"'. ==== tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts (7 errors) ==== @@ -67,5 +66,4 @@ tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTyp function h({ prop = "baz" }: StringUnion) {} ~~~~ !!! error TS2322: Type '"baz"' is not assignable to type '"foo" | "bar"'. -!!! error TS2322: Type '"baz"' is not assignable to type '"bar"'. \ No newline at end of file diff --git a/tests/baselines/reference/contextuallyTypedStringLiteralsInJsxAttributes01.errors.txt b/tests/baselines/reference/contextuallyTypedStringLiteralsInJsxAttributes01.errors.txt index 32b86e455d2..48e11fb1221 100644 --- a/tests/baselines/reference/contextuallyTypedStringLiteralsInJsxAttributes01.errors.txt +++ b/tests/baselines/reference/contextuallyTypedStringLiteralsInJsxAttributes01.errors.txt @@ -1,7 +1,5 @@ tests/cases/conformance/types/contextualTypes/jsxAttributes/contextuallyTypedStringLiteralsInJsxAttributes01.tsx(16,15): error TS2322: Type '"f"' is not assignable to type '"A" | "B" | "C"'. - Type '"f"' is not assignable to type '"C"'. tests/cases/conformance/types/contextualTypes/jsxAttributes/contextuallyTypedStringLiteralsInJsxAttributes01.tsx(17,15): error TS2322: Type '"f"' is not assignable to type '"A" | "B" | "C"'. - Type '"f"' is not assignable to type '"C"'. ==== tests/cases/conformance/types/contextualTypes/jsxAttributes/contextuallyTypedStringLiteralsInJsxAttributes01.tsx (2 errors) ==== @@ -23,8 +21,6 @@ tests/cases/conformance/types/contextualTypes/jsxAttributes/contextuallyTypedStr ; ~~~~~~~~~ !!! error TS2322: Type '"f"' is not assignable to type '"A" | "B" | "C"'. -!!! error TS2322: Type '"f"' is not assignable to type '"C"'. ; ~~~~~~~ -!!! error TS2322: Type '"f"' is not assignable to type '"A" | "B" | "C"'. -!!! error TS2322: Type '"f"' is not assignable to type '"C"'. \ No newline at end of file +!!! error TS2322: Type '"f"' is not assignable to type '"A" | "B" | "C"'. \ No newline at end of file diff --git a/tests/baselines/reference/destructuringParameterDeclaration2.errors.txt b/tests/baselines/reference/destructuringParameterDeclaration2.errors.txt index 114efc14d9c..d68220c8308 100644 --- a/tests/baselines/reference/destructuringParameterDeclaration2.errors.txt +++ b/tests/baselines/reference/destructuringParameterDeclaration2.errors.txt @@ -7,7 +7,6 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts( Type '() => number | string[][] | string' is not assignable to type '() => number | string[][]'. Type 'number | string[][] | string' is not assignable to type 'number | string[][]'. Type 'string' is not assignable to type 'number | string[][]'. - Type 'string' is not assignable to type 'string[][]'. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts(16,8): error TS2371: A parameter initializer is only allowed in a function or constructor implementation. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts(16,16): error TS2371: A parameter initializer is only allowed in a function or constructor implementation. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts(23,14): error TS2345: Argument of type '{ x: string; y: boolean; }' is not assignable to parameter of type '{ x: number; y: any; }'. @@ -29,7 +28,6 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts( tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts(38,4): error TS2345: Argument of type '{ b: boolean; }' is not assignable to parameter of type '{ b: number | string; }'. Types of property 'b' are incompatible. Type 'boolean' is not assignable to type 'number | string'. - Type 'boolean' is not assignable to type 'string'. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts(39,4): error TS2345: Argument of type '[number, number, boolean, boolean]' is not assignable to parameter of type '[any, any, [[any]]]'. Types of property '2' are incompatible. Type 'boolean' is not assignable to type '[[any]]'. @@ -75,7 +73,6 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts( !!! error TS2345: Type '() => number | string[][] | string' is not assignable to type '() => number | string[][]'. !!! error TS2345: Type 'number | string[][] | string' is not assignable to type 'number | string[][]'. !!! error TS2345: Type 'string' is not assignable to type 'number | string[][]'. -!!! error TS2345: Type 'string' is not assignable to type 'string[][]'. // If the declaration includes an initializer expression (which is permitted only @@ -137,7 +134,6 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts( !!! error TS2345: Argument of type '{ b: boolean; }' is not assignable to parameter of type '{ b: number | string; }'. !!! error TS2345: Types of property 'b' are incompatible. !!! error TS2345: Type 'boolean' is not assignable to type 'number | string'. -!!! error TS2345: Type 'boolean' is not assignable to type 'string'. c5([1, 2, false, true]); // Error, implied type is [any, any, [[any]]] ~~~~~~~~~~~~~~~~~~~ !!! error TS2345: Argument of type '[number, number, boolean, boolean]' is not assignable to parameter of type '[any, any, [[any]]]'. diff --git a/tests/baselines/reference/destructuringParameterDeclaration4.errors.txt b/tests/baselines/reference/destructuringParameterDeclaration4.errors.txt index b08c5b942d8..aa5a8e8daea 100644 --- a/tests/baselines/reference/destructuringParameterDeclaration4.errors.txt +++ b/tests/baselines/reference/destructuringParameterDeclaration4.errors.txt @@ -1,7 +1,6 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(11,13): error TS2370: A rest parameter must be of an array type. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(13,13): error TS2370: A rest parameter must be of an array type. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(20,19): error TS2345: Argument of type 'boolean' is not assignable to parameter of type 'number | string'. - Type 'boolean' is not assignable to type 'string'. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(21,7): error TS2304: Cannot find name 'array2'. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(22,4): error TS2345: Argument of type '[number, number, string, boolean, boolean]' is not assignable to parameter of type '[any, any, [[any]]]'. Types of property '2' are incompatible. @@ -43,7 +42,6 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts( a1(1, 2, "hello", true); // Error, parameter type is (number|string)[] ~~~~ !!! error TS2345: Argument of type 'boolean' is not assignable to parameter of type 'number | string'. -!!! error TS2345: Type 'boolean' is not assignable to type 'string'. a1(...array2); // Error parameter type is (number|string)[] ~~~~~~ !!! error TS2304: Cannot find name 'array2'. diff --git a/tests/baselines/reference/errorMessagesIntersectionTypes02.errors.txt b/tests/baselines/reference/errorMessagesIntersectionTypes02.errors.txt index 06e06c87015..6a9dd26706c 100644 --- a/tests/baselines/reference/errorMessagesIntersectionTypes02.errors.txt +++ b/tests/baselines/reference/errorMessagesIntersectionTypes02.errors.txt @@ -1,7 +1,6 @@ tests/cases/compiler/errorMessagesIntersectionTypes02.ts(14,5): error TS2322: Type '{ fooProp: string; } & Bar' is not assignable to type 'FooBar'. Types of property 'fooProp' are incompatible. Type 'string' is not assignable to type '"hello" | "world"'. - Type 'string' is not assignable to type '"world"'. ==== tests/cases/compiler/errorMessagesIntersectionTypes02.ts (1 errors) ==== @@ -23,6 +22,5 @@ tests/cases/compiler/errorMessagesIntersectionTypes02.ts(14,5): error TS2322: Ty !!! error TS2322: Type '{ fooProp: string; } & Bar' is not assignable to type 'FooBar'. !!! error TS2322: Types of property 'fooProp' are incompatible. !!! error TS2322: Type 'string' is not assignable to type '"hello" | "world"'. -!!! error TS2322: Type 'string' is not assignable to type '"world"'. fooProp: "frizzlebizzle" }); \ No newline at end of file diff --git a/tests/baselines/reference/functionAndImportNameConflict.errors.txt b/tests/baselines/reference/functionAndImportNameConflict.errors.txt new file mode 100644 index 00000000000..4ca496cfb65 --- /dev/null +++ b/tests/baselines/reference/functionAndImportNameConflict.errors.txt @@ -0,0 +1,13 @@ +tests/cases/compiler/f2.ts(1,9): error TS2440: Import declaration conflicts with local declaration of 'f' + + +==== tests/cases/compiler/f1.ts (0 errors) ==== + export function f() { + } + +==== tests/cases/compiler/f2.ts (1 errors) ==== + import {f} from './f1'; + ~ +!!! error TS2440: Import declaration conflicts with local declaration of 'f' + export function f() { + } \ No newline at end of file diff --git a/tests/baselines/reference/functionAndImportNameConflict.js b/tests/baselines/reference/functionAndImportNameConflict.js new file mode 100644 index 00000000000..8391823aa3a --- /dev/null +++ b/tests/baselines/reference/functionAndImportNameConflict.js @@ -0,0 +1,21 @@ +//// [tests/cases/compiler/functionAndImportNameConflict.ts] //// + +//// [f1.ts] +export function f() { +} + +//// [f2.ts] +import {f} from './f1'; +export function f() { +} + +//// [f1.js] +"use strict"; +function f() { +} +exports.f = f; +//// [f2.js] +"use strict"; +function f() { +} +exports.f = f; diff --git a/tests/baselines/reference/genericCallWithTupleType.errors.txt b/tests/baselines/reference/genericCallWithTupleType.errors.txt index bcf580320e5..24e0505d009 100644 --- a/tests/baselines/reference/genericCallWithTupleType.errors.txt +++ b/tests/baselines/reference/genericCallWithTupleType.errors.txt @@ -3,7 +3,6 @@ tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTup Type '() => string | number | boolean' is not assignable to type '() => string | number'. Type 'string | number | boolean' is not assignable to type 'string | number'. Type 'boolean' is not assignable to type 'string | number'. - Type 'boolean' is not assignable to type 'number'. tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTupleType.ts(14,1): error TS2322: Type '{ a: string; }' is not assignable to type 'string | number'. Type '{ a: string; }' is not assignable to type 'number'. tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTupleType.ts(22,1): error TS2322: Type '[number, string]' is not assignable to type '[string, number]'. @@ -35,7 +34,6 @@ tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTup !!! error TS2322: Type '() => string | number | boolean' is not assignable to type '() => string | number'. !!! error TS2322: Type 'string | number | boolean' is not assignable to type 'string | number'. !!! error TS2322: Type 'boolean' is not assignable to type 'string | number'. -!!! error TS2322: Type 'boolean' is not assignable to type 'number'. var e3 = i1.tuple1[2]; // {} i1.tuple1[3] = { a: "string" }; ~~~~~~~~~~~~ diff --git a/tests/baselines/reference/inferenceLimit.js b/tests/baselines/reference/inferenceLimit.js new file mode 100644 index 00000000000..a74bf59df44 --- /dev/null +++ b/tests/baselines/reference/inferenceLimit.js @@ -0,0 +1,82 @@ +//// [tests/cases/compiler/inferenceLimit.ts] //// + +//// [file1.ts] +"use strict"; +import * as MyModule from "./mymodule"; + +export class BrokenClass { + + constructor() {} + + public brokenMethod(field: string, value: string) { + return new Promise>((resolve, reject) => { + + let result: Array = []; + + let populateItems = (order) => { + return new Promise((resolve, reject) => { + this.doStuff(order.id) + .then((items) => { + order.items = items; + resolve(order); + }); + }); + }; + + return Promise.all(result.map(populateItems)) + .then((orders: Array) => { + resolve(orders); + }); + }); + } + + public async doStuff(id: number) { + return; + } +} + +//// [mymodule.ts] +export interface MyModel { + id: number; +} + +//// [mymodule.js] +"use strict"; +//// [file1.js] +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments)).next()); + }); +}; +class BrokenClass { + constructor() { + } + brokenMethod(field, value) { + return new Promise((resolve, reject) => { + let result = []; + let populateItems = (order) => { + return new Promise((resolve, reject) => { + this.doStuff(order.id) + .then((items) => { + order.items = items; + resolve(order); + }); + }); + }; + return Promise.all(result.map(populateItems)) + .then((orders) => { + resolve(orders); + }); + }); + } + doStuff(id) { + return __awaiter(this, void 0, void 0, function* () { + return; + }); + } +} +exports.BrokenClass = BrokenClass; diff --git a/tests/baselines/reference/inferenceLimit.symbols b/tests/baselines/reference/inferenceLimit.symbols new file mode 100644 index 00000000000..8a338b80307 --- /dev/null +++ b/tests/baselines/reference/inferenceLimit.symbols @@ -0,0 +1,101 @@ +=== tests/cases/compiler/file1.ts === +"use strict"; +import * as MyModule from "./mymodule"; +>MyModule : Symbol(MyModule, Decl(file1.ts, 1, 6)) + +export class BrokenClass { +>BrokenClass : Symbol(BrokenClass, Decl(file1.ts, 1, 39)) + + constructor() {} + + public brokenMethod(field: string, value: string) { +>brokenMethod : Symbol(BrokenClass.brokenMethod, Decl(file1.ts, 5, 18)) +>field : Symbol(field, Decl(file1.ts, 7, 22)) +>value : Symbol(value, Decl(file1.ts, 7, 36)) + + return new Promise>((resolve, reject) => { +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>MyModule : Symbol(MyModule, Decl(file1.ts, 1, 6)) +>MyModel : Symbol(MyModule.MyModel, Decl(mymodule.ts, 0, 0)) +>resolve : Symbol(resolve, Decl(file1.ts, 8, 47)) +>reject : Symbol(reject, Decl(file1.ts, 8, 55)) + + let result: Array = []; +>result : Symbol(result, Decl(file1.ts, 10, 7)) +>Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>MyModule : Symbol(MyModule, Decl(file1.ts, 1, 6)) +>MyModel : Symbol(MyModule.MyModel, Decl(mymodule.ts, 0, 0)) + + let populateItems = (order) => { +>populateItems : Symbol(populateItems, Decl(file1.ts, 12, 7)) +>order : Symbol(order, Decl(file1.ts, 12, 25)) + + return new Promise((resolve, reject) => { +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>resolve : Symbol(resolve, Decl(file1.ts, 13, 26)) +>reject : Symbol(reject, Decl(file1.ts, 13, 34)) + + this.doStuff(order.id) +>this.doStuff(order.id) .then : Symbol(Promise.then, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>this.doStuff : Symbol(BrokenClass.doStuff, Decl(file1.ts, 27, 3)) +>this : Symbol(BrokenClass, Decl(file1.ts, 1, 39)) +>doStuff : Symbol(BrokenClass.doStuff, Decl(file1.ts, 27, 3)) +>order : Symbol(order, Decl(file1.ts, 12, 25)) + + .then((items) => { +>then : Symbol(Promise.then, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>items : Symbol(items, Decl(file1.ts, 15, 17)) + + order.items = items; +>order : Symbol(order, Decl(file1.ts, 12, 25)) +>items : Symbol(items, Decl(file1.ts, 15, 17)) + + resolve(order); +>resolve : Symbol(resolve, Decl(file1.ts, 13, 26)) +>order : Symbol(order, Decl(file1.ts, 12, 25)) + + }); + }); + }; + + return Promise.all(result.map(populateItems)) +>Promise.all(result.map(populateItems)) .then : Symbol(Promise.then, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>Promise.all : Symbol(PromiseConstructor.all, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>all : Symbol(PromiseConstructor.all, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>result.map : Symbol(Array.map, Decl(lib.d.ts, --, --)) +>result : Symbol(result, Decl(file1.ts, 10, 7)) +>map : Symbol(Array.map, Decl(lib.d.ts, --, --)) +>populateItems : Symbol(populateItems, Decl(file1.ts, 12, 7)) + + .then((orders: Array) => { +>then : Symbol(Promise.then, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>orders : Symbol(orders, Decl(file1.ts, 23, 13)) +>Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>MyModule : Symbol(MyModule, Decl(file1.ts, 1, 6)) +>MyModel : Symbol(MyModule.MyModel, Decl(mymodule.ts, 0, 0)) + + resolve(orders); +>resolve : Symbol(resolve, Decl(file1.ts, 8, 47)) +>orders : Symbol(orders, Decl(file1.ts, 23, 13)) + + }); + }); + } + + public async doStuff(id: number) { +>doStuff : Symbol(BrokenClass.doStuff, Decl(file1.ts, 27, 3)) +>id : Symbol(id, Decl(file1.ts, 29, 23)) + + return; + } +} + +=== tests/cases/compiler/mymodule.ts === +export interface MyModel { +>MyModel : Symbol(MyModel, Decl(mymodule.ts, 0, 0)) + + id: number; +>id : Symbol(MyModel.id, Decl(mymodule.ts, 0, 26)) +} diff --git a/tests/baselines/reference/inferenceLimit.types b/tests/baselines/reference/inferenceLimit.types new file mode 100644 index 00000000000..58f9b1e4ae0 --- /dev/null +++ b/tests/baselines/reference/inferenceLimit.types @@ -0,0 +1,123 @@ +=== tests/cases/compiler/file1.ts === +"use strict"; +>"use strict" : string + +import * as MyModule from "./mymodule"; +>MyModule : typeof MyModule + +export class BrokenClass { +>BrokenClass : BrokenClass + + constructor() {} + + public brokenMethod(field: string, value: string) { +>brokenMethod : (field: string, value: string) => Promise +>field : string +>value : string + + return new Promise>((resolve, reject) => { +>new Promise>((resolve, reject) => { let result: Array = []; let populateItems = (order) => { return new Promise((resolve, reject) => { this.doStuff(order.id) .then((items) => { order.items = items; resolve(order); }); }); }; return Promise.all(result.map(populateItems)) .then((orders: Array) => { resolve(orders); }); }) : Promise +>Promise : PromiseConstructor +>Array : T[] +>MyModule : any +>MyModel : MyModule.MyModel +>(resolve, reject) => { let result: Array = []; let populateItems = (order) => { return new Promise((resolve, reject) => { this.doStuff(order.id) .then((items) => { order.items = items; resolve(order); }); }); }; return Promise.all(result.map(populateItems)) .then((orders: Array) => { resolve(orders); }); } : (resolve: (value?: MyModule.MyModel[] | PromiseLike) => void, reject: (reason?: any) => void) => Promise +>resolve : (value?: MyModule.MyModel[] | PromiseLike) => void +>reject : (reason?: any) => void + + let result: Array = []; +>result : MyModule.MyModel[] +>Array : T[] +>MyModule : any +>MyModel : MyModule.MyModel +>[] : undefined[] + + let populateItems = (order) => { +>populateItems : (order: any) => Promise<{}> +>(order) => { return new Promise((resolve, reject) => { this.doStuff(order.id) .then((items) => { order.items = items; resolve(order); }); }); } : (order: any) => Promise<{}> +>order : any + + return new Promise((resolve, reject) => { +>new Promise((resolve, reject) => { this.doStuff(order.id) .then((items) => { order.items = items; resolve(order); }); }) : Promise<{}> +>Promise : PromiseConstructor +>(resolve, reject) => { this.doStuff(order.id) .then((items) => { order.items = items; resolve(order); }); } : (resolve: (value?: {} | PromiseLike<{}>) => void, reject: (reason?: any) => void) => void +>resolve : (value?: {} | PromiseLike<{}>) => void +>reject : (reason?: any) => void + + this.doStuff(order.id) +>this.doStuff(order.id) .then((items) => { order.items = items; resolve(order); }) : Promise +>this.doStuff(order.id) .then : { (onfulfilled?: (value: void) => TResult | PromiseLike, onrejected?: (reason: any) => TResult | PromiseLike): Promise; (onfulfilled?: (value: void) => TResult | PromiseLike, onrejected?: (reason: any) => void): Promise; } +>this.doStuff(order.id) : Promise +>this.doStuff : (id: number) => Promise +>this : this +>doStuff : (id: number) => Promise +>order.id : any +>order : any +>id : any + + .then((items) => { +>then : { (onfulfilled?: (value: void) => TResult | PromiseLike, onrejected?: (reason: any) => TResult | PromiseLike): Promise; (onfulfilled?: (value: void) => TResult | PromiseLike, onrejected?: (reason: any) => void): Promise; } +>(items) => { order.items = items; resolve(order); } : (items: void) => void +>items : void + + order.items = items; +>order.items = items : void +>order.items : any +>order : any +>items : any +>items : void + + resolve(order); +>resolve(order) : void +>resolve : (value?: {} | PromiseLike<{}>) => void +>order : any + + }); + }); + }; + + return Promise.all(result.map(populateItems)) +>Promise.all(result.map(populateItems)) .then((orders: Array) => { resolve(orders); }) : Promise +>Promise.all(result.map(populateItems)) .then : { (onfulfilled?: (value: {}[]) => TResult | PromiseLike, onrejected?: (reason: any) => TResult | PromiseLike): Promise; (onfulfilled?: (value: {}[]) => TResult | PromiseLike, onrejected?: (reason: any) => void): Promise; } +>Promise.all(result.map(populateItems)) : Promise<{}[]> +>Promise.all : { (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike, T8 | PromiseLike, T9 | PromiseLike, T10 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike, T8 | PromiseLike, T9 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike, T8 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6, T7]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike]): Promise<[T1, T2, T3, T4, T5]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike]): Promise<[T1, T2, T3, T4]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike]): Promise<[T1, T2, T3]>; (values: [T1 | PromiseLike, T2 | PromiseLike]): Promise<[T1, T2]>; (values: Iterable>): Promise; } +>Promise : PromiseConstructor +>all : { (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike, T8 | PromiseLike, T9 | PromiseLike, T10 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike, T8 | PromiseLike, T9 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike, T8 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6, T7]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike]): Promise<[T1, T2, T3, T4, T5]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike]): Promise<[T1, T2, T3, T4]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike]): Promise<[T1, T2, T3]>; (values: [T1 | PromiseLike, T2 | PromiseLike]): Promise<[T1, T2]>; (values: Iterable>): Promise; } +>result.map(populateItems) : Promise<{}>[] +>result.map : (callbackfn: (value: MyModule.MyModel, index: number, array: MyModule.MyModel[]) => U, thisArg?: any) => U[] +>result : MyModule.MyModel[] +>map : (callbackfn: (value: MyModule.MyModel, index: number, array: MyModule.MyModel[]) => U, thisArg?: any) => U[] +>populateItems : (order: any) => Promise<{}> + + .then((orders: Array) => { +>then : { (onfulfilled?: (value: {}[]) => TResult | PromiseLike, onrejected?: (reason: any) => TResult | PromiseLike): Promise; (onfulfilled?: (value: {}[]) => TResult | PromiseLike, onrejected?: (reason: any) => void): Promise; } +>(orders: Array) => { resolve(orders); } : (orders: MyModule.MyModel[]) => void +>orders : MyModule.MyModel[] +>Array : T[] +>MyModule : any +>MyModel : MyModule.MyModel + + resolve(orders); +>resolve(orders) : void +>resolve : (value?: MyModule.MyModel[] | PromiseLike) => void +>orders : MyModule.MyModel[] + + }); + }); + } + + public async doStuff(id: number) { +>doStuff : (id: number) => Promise +>id : number + + return; + } +} + +=== tests/cases/compiler/mymodule.ts === +export interface MyModel { +>MyModel : MyModel + + id: number; +>id : number +} diff --git a/tests/baselines/reference/iteratorSpreadInCall6.errors.txt b/tests/baselines/reference/iteratorSpreadInCall6.errors.txt index 0a0da985ace..ee9945f7af6 100644 --- a/tests/baselines/reference/iteratorSpreadInCall6.errors.txt +++ b/tests/baselines/reference/iteratorSpreadInCall6.errors.txt @@ -1,12 +1,10 @@ tests/cases/conformance/es6/spread/iteratorSpreadInCall6.ts(1,28): error TS2345: Argument of type 'string' is not assignable to parameter of type 'symbol | number'. - Type 'string' is not assignable to type 'number'. ==== tests/cases/conformance/es6/spread/iteratorSpreadInCall6.ts (1 errors) ==== foo(...new SymbolIterator, ...new StringIterator); ~~~~~~~~~~~~~~~~~~~~~ !!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'symbol | number'. -!!! error TS2345: Type 'string' is not assignable to type 'number'. function foo(...s: (symbol | number)[]) { } class SymbolIterator { diff --git a/tests/baselines/reference/jsxReactTestSuite.symbols b/tests/baselines/reference/jsxReactTestSuite.symbols index 1ee71370dbc..956b4cff6f7 100644 --- a/tests/baselines/reference/jsxReactTestSuite.symbols +++ b/tests/baselines/reference/jsxReactTestSuite.symbols @@ -56,9 +56,11 @@ declare var hasOwnProperty:any; >div : Symbol(unknown) {foo}
{bar}
+>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11)) >foo : Symbol(foo, Decl(jsxReactTestSuite.tsx, 7, 11)) >br : Symbol(unknown) >bar : Symbol(bar, Decl(jsxReactTestSuite.tsx, 8, 11)) +>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11))
>br : Symbol(unknown) @@ -68,12 +70,20 @@ declare var hasOwnProperty:any; +>Composite : Symbol(Composite, Decl(jsxReactTestSuite.tsx, 3, 11)) + {this.props.children} ; +>Composite : Symbol(Composite, Decl(jsxReactTestSuite.tsx, 3, 11)) +>Composite : Symbol(Composite, Decl(jsxReactTestSuite.tsx, 3, 11)) + +>Composite2 : Symbol(Composite2, Decl(jsxReactTestSuite.tsx, 4, 11)) + ; +>Composite : Symbol(Composite, Decl(jsxReactTestSuite.tsx, 3, 11)) var x = >x : Symbol(x, Decl(jsxReactTestSuite.tsx, 10, 11), Decl(jsxReactTestSuite.tsx, 35, 3)) @@ -164,13 +174,17 @@ var x = >hasOwnProperty : Symbol(unknown) ; +>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11)) >constructor : Symbol(unknown) ; +>Namespace : Symbol(Namespace, Decl(jsxReactTestSuite.tsx, 6, 11)) ; +>Namespace : Symbol(Namespace, Decl(jsxReactTestSuite.tsx, 6, 11)) Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11)) >x : Symbol(x, Decl(jsxReactTestSuite.tsx, 10, 11), Decl(jsxReactTestSuite.tsx, 35, 3)) >y : Symbol(unknown) @@ -178,6 +192,8 @@ var x = >z : Symbol(unknown) Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11)) + {...this.props} sound="moo" />; >sound : Symbol(unknown) @@ -185,6 +201,7 @@ var x = >font-face : Symbol(unknown) ; +>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11)) >x : Symbol(unknown) >y : Symbol(y, Decl(jsxReactTestSuite.tsx, 9, 11)) @@ -192,34 +209,43 @@ var x = >x-component : Symbol(unknown) ; +>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11)) >x : Symbol(x, Decl(jsxReactTestSuite.tsx, 10, 11), Decl(jsxReactTestSuite.tsx, 35, 3)) ; +>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11)) >x : Symbol(x, Decl(jsxReactTestSuite.tsx, 10, 11), Decl(jsxReactTestSuite.tsx, 35, 3)) >y : Symbol(unknown) ; +>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11)) >x : Symbol(x, Decl(jsxReactTestSuite.tsx, 10, 11), Decl(jsxReactTestSuite.tsx, 35, 3)) >y : Symbol(unknown) >z : Symbol(unknown) ; +>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11)) >x : Symbol(unknown) >y : Symbol(y, Decl(jsxReactTestSuite.tsx, 9, 11)) ; +>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11)) >x : Symbol(unknown) >y : Symbol(unknown) >z : Symbol(z, Decl(jsxReactTestSuite.tsx, 11, 11)) >z : Symbol(z, Decl(jsxReactTestSuite.tsx, 11, 11)) +>Child : Symbol(Child, Decl(jsxReactTestSuite.tsx, 5, 11)) +>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11)) Text; +>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11)) >x : Symbol(unknown) >z : Symbol(z, Decl(jsxReactTestSuite.tsx, 11, 11)) >y : Symbol(y, Decl(jsxReactTestSuite.tsx, 113, 27)) >z : Symbol(z, Decl(jsxReactTestSuite.tsx, 11, 11)) >z : Symbol(unknown) +>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11)) diff --git a/tests/baselines/reference/jsxReactTestSuite.types b/tests/baselines/reference/jsxReactTestSuite.types index 88c2c278e59..8bab7ce6e7d 100644 --- a/tests/baselines/reference/jsxReactTestSuite.types +++ b/tests/baselines/reference/jsxReactTestSuite.types @@ -235,11 +235,14 @@ var x = ; > : any +>Namespace.Component : any >Namespace : any >Component : any ; > : any +>Namespace.DeepNamespace.Component : any +>Namespace.DeepNamespace : any >Namespace : any >DeepNamespace : any >Component : any diff --git a/tests/baselines/reference/logicalAndOperatorWithEveryType.types b/tests/baselines/reference/logicalAndOperatorWithEveryType.types index bd913e94da5..b2628eed921 100644 --- a/tests/baselines/reference/logicalAndOperatorWithEveryType.types +++ b/tests/baselines/reference/logicalAndOperatorWithEveryType.types @@ -623,7 +623,7 @@ var rj8 = a8 && undefined; var rj9 = null && undefined; >rj9 : any ->null && undefined : undefined +>null && undefined : null >null : null >undefined : undefined diff --git a/tests/baselines/reference/logicalNotOperatorInvalidOperations.errors.txt b/tests/baselines/reference/logicalNotOperatorInvalidOperations.errors.txt index 07262962b08..c7d66e17f9d 100644 --- a/tests/baselines/reference/logicalNotOperatorInvalidOperations.errors.txt +++ b/tests/baselines/reference/logicalNotOperatorInvalidOperations.errors.txt @@ -1,19 +1,13 @@ -tests/cases/conformance/expressions/unaryOperators/logicalNotOperator/logicalNotOperatorInvalidOperations.ts(5,17): error TS1005: ',' expected. -tests/cases/conformance/expressions/unaryOperators/logicalNotOperator/logicalNotOperatorInvalidOperations.ts(5,18): error TS1109: Expression expected. tests/cases/conformance/expressions/unaryOperators/logicalNotOperator/logicalNotOperatorInvalidOperations.ts(8,16): error TS2365: Operator '+' cannot be applied to types 'boolean' and 'number'. tests/cases/conformance/expressions/unaryOperators/logicalNotOperator/logicalNotOperatorInvalidOperations.ts(11,16): error TS1109: Expression expected. -==== tests/cases/conformance/expressions/unaryOperators/logicalNotOperator/logicalNotOperatorInvalidOperations.ts (4 errors) ==== +==== tests/cases/conformance/expressions/unaryOperators/logicalNotOperator/logicalNotOperatorInvalidOperations.ts (2 errors) ==== // Unary operator ! var b: number; // operand before ! var BOOLEAN1 = b!; //expect error - ~ -!!! error TS1005: ',' expected. - ~ -!!! error TS1109: Expression expected. // miss parentheses var BOOLEAN2 = !b + b; diff --git a/tests/baselines/reference/logicalNotOperatorInvalidOperations.js b/tests/baselines/reference/logicalNotOperatorInvalidOperations.js index 7b16f2ef36f..0cb941b0e41 100644 --- a/tests/baselines/reference/logicalNotOperatorInvalidOperations.js +++ b/tests/baselines/reference/logicalNotOperatorInvalidOperations.js @@ -15,8 +15,7 @@ var BOOLEAN3 =!; // Unary operator ! var b; // operand before ! -var BOOLEAN1 = b; -!; //expect error +var BOOLEAN1 = b; //expect error // miss parentheses var BOOLEAN2 = !b + b; // miss an operand diff --git a/tests/baselines/reference/mergeWithImportedNamespace.js b/tests/baselines/reference/mergeWithImportedNamespace.js new file mode 100644 index 00000000000..60f6fedd3f2 --- /dev/null +++ b/tests/baselines/reference/mergeWithImportedNamespace.js @@ -0,0 +1,20 @@ +//// [tests/cases/compiler/mergeWithImportedNamespace.ts] //// + +//// [f1.ts] +export namespace N { export var x = 1; } + +//// [f2.ts] +import {N} from "./f1"; +// partial revert of https://github.com/Microsoft/TypeScript/pull/7583 to prevent breaking changes +export namespace N { + export interface I {x: any} +} + +//// [f1.js] +"use strict"; +var N; +(function (N) { + N.x = 1; +})(N = exports.N || (exports.N = {})); +//// [f2.js] +"use strict"; diff --git a/tests/baselines/reference/mergeWithImportedNamespace.symbols b/tests/baselines/reference/mergeWithImportedNamespace.symbols new file mode 100644 index 00000000000..58b0f0a811f --- /dev/null +++ b/tests/baselines/reference/mergeWithImportedNamespace.symbols @@ -0,0 +1,17 @@ +=== tests/cases/compiler/f1.ts === +export namespace N { export var x = 1; } +>N : Symbol(N, Decl(f1.ts, 0, 0)) +>x : Symbol(x, Decl(f1.ts, 0, 31)) + +=== tests/cases/compiler/f2.ts === +import {N} from "./f1"; +>N : Symbol(N, Decl(f2.ts, 0, 8), Decl(f2.ts, 0, 23)) + +// partial revert of https://github.com/Microsoft/TypeScript/pull/7583 to prevent breaking changes +export namespace N { +>N : Symbol(N, Decl(f2.ts, 0, 23)) + + export interface I {x: any} +>I : Symbol(I, Decl(f2.ts, 2, 20)) +>x : Symbol(I.x, Decl(f2.ts, 3, 24)) +} diff --git a/tests/baselines/reference/mergeWithImportedNamespace.types b/tests/baselines/reference/mergeWithImportedNamespace.types new file mode 100644 index 00000000000..d6c1df3b609 --- /dev/null +++ b/tests/baselines/reference/mergeWithImportedNamespace.types @@ -0,0 +1,18 @@ +=== tests/cases/compiler/f1.ts === +export namespace N { export var x = 1; } +>N : typeof N +>x : number +>1 : number + +=== tests/cases/compiler/f2.ts === +import {N} from "./f1"; +>N : typeof N + +// partial revert of https://github.com/Microsoft/TypeScript/pull/7583 to prevent breaking changes +export namespace N { +>N : any + + export interface I {x: any} +>I : I +>x : any +} diff --git a/tests/baselines/reference/mergeWithImportedType.js b/tests/baselines/reference/mergeWithImportedType.js new file mode 100644 index 00000000000..89fc353d395 --- /dev/null +++ b/tests/baselines/reference/mergeWithImportedType.js @@ -0,0 +1,18 @@ +//// [tests/cases/compiler/mergeWithImportedType.ts] //// + +//// [f1.ts] +export enum E {X} + +//// [f2.ts] +import {E} from "./f1"; +// partial revert of https://github.com/Microsoft/TypeScript/pull/7583 to prevent breaking changes +export type E = E; + +//// [f1.js] +"use strict"; +(function (E) { + E[E["X"] = 0] = "X"; +})(exports.E || (exports.E = {})); +var E = exports.E; +//// [f2.js] +"use strict"; diff --git a/tests/baselines/reference/mergeWithImportedType.symbols b/tests/baselines/reference/mergeWithImportedType.symbols new file mode 100644 index 00000000000..d14d76f91e7 --- /dev/null +++ b/tests/baselines/reference/mergeWithImportedType.symbols @@ -0,0 +1,14 @@ +=== tests/cases/compiler/f1.ts === +export enum E {X} +>E : Symbol(E, Decl(f1.ts, 0, 0)) +>X : Symbol(E.X, Decl(f1.ts, 0, 15)) + +=== tests/cases/compiler/f2.ts === +import {E} from "./f1"; +>E : Symbol(E, Decl(f2.ts, 0, 8), Decl(f2.ts, 0, 23)) + +// partial revert of https://github.com/Microsoft/TypeScript/pull/7583 to prevent breaking changes +export type E = E; +>E : Symbol(E, Decl(f2.ts, 0, 23)) +>E : Symbol(E, Decl(f2.ts, 0, 8), Decl(f2.ts, 0, 23)) + diff --git a/tests/baselines/reference/mergeWithImportedType.types b/tests/baselines/reference/mergeWithImportedType.types new file mode 100644 index 00000000000..583492444c5 --- /dev/null +++ b/tests/baselines/reference/mergeWithImportedType.types @@ -0,0 +1,14 @@ +=== tests/cases/compiler/f1.ts === +export enum E {X} +>E : E +>X : E + +=== tests/cases/compiler/f2.ts === +import {E} from "./f1"; +>E : typeof E + +// partial revert of https://github.com/Microsoft/TypeScript/pull/7583 to prevent breaking changes +export type E = E; +>E : E +>E : E + diff --git a/tests/baselines/reference/privateClassPropertyAccessibleWithinNestedClass.js b/tests/baselines/reference/privateClassPropertyAccessibleWithinNestedClass.js new file mode 100644 index 00000000000..3bb0a7da3ea --- /dev/null +++ b/tests/baselines/reference/privateClassPropertyAccessibleWithinNestedClass.js @@ -0,0 +1,84 @@ +//// [privateClassPropertyAccessibleWithinNestedClass.ts] +// no errors + +class C { + private x: string; + private get y() { return this.x; } + private set y(x) { this.y = this.x; } + private foo() { return this.foo; } + + private static x: string; + private static get y() { return this.x; } + private static set y(x) { this.y = this.x; } + private static foo() { return this.foo; } + private static bar() { this.foo(); } + + private bar() { + class C2 { + private foo() { + let x: C; + var x1 = x.foo; + var x2 = x.bar; + var x3 = x.x; + var x4 = x.y; + + var sx1 = C.x; + var sx2 = C.y; + var sx3 = C.bar; + var sx4 = C.foo; + + let y = new C(); + var y1 = y.foo; + var y2 = y.bar; + var y3 = y.x; + var y4 = y.y; + } + } + } +} + +//// [privateClassPropertyAccessibleWithinNestedClass.js] +// no errors +var C = (function () { + function C() { + } + Object.defineProperty(C.prototype, "y", { + get: function () { return this.x; }, + set: function (x) { this.y = this.x; }, + enumerable: true, + configurable: true + }); + C.prototype.foo = function () { return this.foo; }; + Object.defineProperty(C, "y", { + get: function () { return this.x; }, + set: function (x) { this.y = this.x; }, + enumerable: true, + configurable: true + }); + C.foo = function () { return this.foo; }; + C.bar = function () { this.foo(); }; + C.prototype.bar = function () { + var C2 = (function () { + function C2() { + } + C2.prototype.foo = function () { + var x; + var x1 = x.foo; + var x2 = x.bar; + var x3 = x.x; + var x4 = x.y; + var sx1 = C.x; + var sx2 = C.y; + var sx3 = C.bar; + var sx4 = C.foo; + var y = new C(); + var y1 = y.foo; + var y2 = y.bar; + var y3 = y.x; + var y4 = y.y; + }; + return C2; + }()); + }; + return C; +}()); diff --git a/tests/baselines/reference/privateClassPropertyAccessibleWithinNestedClass.symbols b/tests/baselines/reference/privateClassPropertyAccessibleWithinNestedClass.symbols new file mode 100644 index 00000000000..4aa6e6df5d9 --- /dev/null +++ b/tests/baselines/reference/privateClassPropertyAccessibleWithinNestedClass.symbols @@ -0,0 +1,154 @@ +=== tests/cases/conformance/classes/members/accessibility/privateClassPropertyAccessibleWithinNestedClass.ts === +// no errors + +class C { +>C : Symbol(C, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) + + private x: string; +>x : Symbol(C.x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 2, 9)) + + private get y() { return this.x; } +>y : Symbol(C.y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 3, 22), Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 4, 38)) +>this.x : Symbol(C.x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 2, 9)) +>this : Symbol(C, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>x : Symbol(C.x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 2, 9)) + + private set y(x) { this.y = this.x; } +>y : Symbol(C.y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 3, 22), Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 4, 38)) +>x : Symbol(x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 5, 18)) +>this.y : Symbol(C.y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 3, 22), Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 4, 38)) +>this : Symbol(C, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>y : Symbol(C.y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 3, 22), Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 4, 38)) +>this.x : Symbol(C.x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 2, 9)) +>this : Symbol(C, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>x : Symbol(C.x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 2, 9)) + + private foo() { return this.foo; } +>foo : Symbol(C.foo, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 5, 41)) +>this.foo : Symbol(C.foo, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 5, 41)) +>this : Symbol(C, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>foo : Symbol(C.foo, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 5, 41)) + + private static x: string; +>x : Symbol(C.x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 6, 38)) + + private static get y() { return this.x; } +>y : Symbol(C.y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 8, 29), Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 9, 45)) +>this.x : Symbol(C.x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 6, 38)) +>this : Symbol(C, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>x : Symbol(C.x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 6, 38)) + + private static set y(x) { this.y = this.x; } +>y : Symbol(C.y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 8, 29), Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 9, 45)) +>x : Symbol(x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 10, 25)) +>this.y : Symbol(C.y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 8, 29), Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 9, 45)) +>this : Symbol(C, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>y : Symbol(C.y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 8, 29), Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 9, 45)) +>this.x : Symbol(C.x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 6, 38)) +>this : Symbol(C, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>x : Symbol(C.x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 6, 38)) + + private static foo() { return this.foo; } +>foo : Symbol(C.foo, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 10, 48)) +>this.foo : Symbol(C.foo, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 10, 48)) +>this : Symbol(C, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>foo : Symbol(C.foo, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 10, 48)) + + private static bar() { this.foo(); } +>bar : Symbol(C.bar, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 11, 45)) +>this.foo : Symbol(C.foo, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 10, 48)) +>this : Symbol(C, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>foo : Symbol(C.foo, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 10, 48)) + + private bar() { +>bar : Symbol(C.bar, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 12, 40)) + + class C2 { +>C2 : Symbol(C2, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 14, 19)) + + private foo() { +>foo : Symbol(C2.foo, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 15, 18)) + + let x: C; +>x : Symbol(x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 17, 19)) +>C : Symbol(C, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) + + var x1 = x.foo; +>x1 : Symbol(x1, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 18, 19)) +>x.foo : Symbol(C.foo, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 5, 41)) +>x : Symbol(x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 17, 19)) +>foo : Symbol(C.foo, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 5, 41)) + + var x2 = x.bar; +>x2 : Symbol(x2, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 19, 19)) +>x.bar : Symbol(C.bar, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 12, 40)) +>x : Symbol(x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 17, 19)) +>bar : Symbol(C.bar, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 12, 40)) + + var x3 = x.x; +>x3 : Symbol(x3, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 20, 19)) +>x.x : Symbol(C.x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 2, 9)) +>x : Symbol(x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 17, 19)) +>x : Symbol(C.x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 2, 9)) + + var x4 = x.y; +>x4 : Symbol(x4, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 21, 19)) +>x.y : Symbol(C.y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 3, 22), Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 4, 38)) +>x : Symbol(x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 17, 19)) +>y : Symbol(C.y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 3, 22), Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 4, 38)) + + var sx1 = C.x; +>sx1 : Symbol(sx1, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 23, 19)) +>C.x : Symbol(C.x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 6, 38)) +>C : Symbol(C, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>x : Symbol(C.x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 6, 38)) + + var sx2 = C.y; +>sx2 : Symbol(sx2, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 24, 19)) +>C.y : Symbol(C.y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 8, 29), Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 9, 45)) +>C : Symbol(C, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>y : Symbol(C.y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 8, 29), Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 9, 45)) + + var sx3 = C.bar; +>sx3 : Symbol(sx3, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 25, 19)) +>C.bar : Symbol(C.bar, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 11, 45)) +>C : Symbol(C, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>bar : Symbol(C.bar, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 11, 45)) + + var sx4 = C.foo; +>sx4 : Symbol(sx4, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 26, 19)) +>C.foo : Symbol(C.foo, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 10, 48)) +>C : Symbol(C, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>foo : Symbol(C.foo, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 10, 48)) + + let y = new C(); +>y : Symbol(y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 28, 19)) +>C : Symbol(C, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) + + var y1 = y.foo; +>y1 : Symbol(y1, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 29, 19)) +>y.foo : Symbol(C.foo, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 5, 41)) +>y : Symbol(y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 28, 19)) +>foo : Symbol(C.foo, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 5, 41)) + + var y2 = y.bar; +>y2 : Symbol(y2, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 30, 19)) +>y.bar : Symbol(C.bar, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 12, 40)) +>y : Symbol(y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 28, 19)) +>bar : Symbol(C.bar, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 12, 40)) + + var y3 = y.x; +>y3 : Symbol(y3, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 31, 19)) +>y.x : Symbol(C.x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 2, 9)) +>y : Symbol(y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 28, 19)) +>x : Symbol(C.x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 2, 9)) + + var y4 = y.y; +>y4 : Symbol(y4, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 32, 19)) +>y.y : Symbol(C.y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 3, 22), Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 4, 38)) +>y : Symbol(y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 28, 19)) +>y : Symbol(C.y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 3, 22), Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 4, 38)) + } + } + } +} diff --git a/tests/baselines/reference/privateClassPropertyAccessibleWithinNestedClass.types b/tests/baselines/reference/privateClassPropertyAccessibleWithinNestedClass.types new file mode 100644 index 00000000000..ee8eb82b940 --- /dev/null +++ b/tests/baselines/reference/privateClassPropertyAccessibleWithinNestedClass.types @@ -0,0 +1,158 @@ +=== tests/cases/conformance/classes/members/accessibility/privateClassPropertyAccessibleWithinNestedClass.ts === +// no errors + +class C { +>C : C + + private x: string; +>x : string + + private get y() { return this.x; } +>y : string +>this.x : string +>this : this +>x : string + + private set y(x) { this.y = this.x; } +>y : string +>x : string +>this.y = this.x : string +>this.y : string +>this : this +>y : string +>this.x : string +>this : this +>x : string + + private foo() { return this.foo; } +>foo : () => any +>this.foo : () => any +>this : this +>foo : () => any + + private static x: string; +>x : string + + private static get y() { return this.x; } +>y : string +>this.x : string +>this : typeof C +>x : string + + private static set y(x) { this.y = this.x; } +>y : string +>x : string +>this.y = this.x : string +>this.y : string +>this : typeof C +>y : string +>this.x : string +>this : typeof C +>x : string + + private static foo() { return this.foo; } +>foo : () => typeof C.foo +>this.foo : () => typeof C.foo +>this : typeof C +>foo : () => typeof C.foo + + private static bar() { this.foo(); } +>bar : () => void +>this.foo() : () => typeof C.foo +>this.foo : () => typeof C.foo +>this : typeof C +>foo : () => typeof C.foo + + private bar() { +>bar : () => void + + class C2 { +>C2 : C2 + + private foo() { +>foo : () => void + + let x: C; +>x : C +>C : C + + var x1 = x.foo; +>x1 : () => any +>x.foo : () => any +>x : C +>foo : () => any + + var x2 = x.bar; +>x2 : () => void +>x.bar : () => void +>x : C +>bar : () => void + + var x3 = x.x; +>x3 : string +>x.x : string +>x : C +>x : string + + var x4 = x.y; +>x4 : string +>x.y : string +>x : C +>y : string + + var sx1 = C.x; +>sx1 : string +>C.x : string +>C : typeof C +>x : string + + var sx2 = C.y; +>sx2 : string +>C.y : string +>C : typeof C +>y : string + + var sx3 = C.bar; +>sx3 : () => void +>C.bar : () => void +>C : typeof C +>bar : () => void + + var sx4 = C.foo; +>sx4 : () => typeof C.foo +>C.foo : () => typeof C.foo +>C : typeof C +>foo : () => typeof C.foo + + let y = new C(); +>y : C +>new C() : C +>C : typeof C + + var y1 = y.foo; +>y1 : () => any +>y.foo : () => any +>y : C +>foo : () => any + + var y2 = y.bar; +>y2 : () => void +>y.bar : () => void +>y : C +>bar : () => void + + var y3 = y.x; +>y3 : string +>y.x : string +>y : C +>x : string + + var y4 = y.y; +>y4 : string +>y.y : string +>y : C +>y : string + } + } + } +} diff --git a/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedClass.js b/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedClass.js new file mode 100644 index 00000000000..2bc544e046e --- /dev/null +++ b/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedClass.js @@ -0,0 +1,84 @@ +//// [protectedClassPropertyAccessibleWithinNestedClass.ts] +// no errors + +class C { + protected x: string; + protected get y() { return this.x; } + protected set y(x) { this.y = this.x; } + protected foo() { return this.foo; } + + protected static x: string; + protected static get y() { return this.x; } + protected static set y(x) { this.y = this.x; } + protected static foo() { return this.foo; } + protected static bar() { this.foo(); } + + protected bar() { + class C2 { + protected foo() { + let x: C; + var x1 = x.foo; + var x2 = x.bar; + var x3 = x.x; + var x4 = x.y; + + var sx1 = C.x; + var sx2 = C.y; + var sx3 = C.bar; + var sx4 = C.foo; + + let y = new C(); + var y1 = y.foo; + var y2 = y.bar; + var y3 = y.x; + var y4 = y.y; + } + } + } +} + +//// [protectedClassPropertyAccessibleWithinNestedClass.js] +// no errors +var C = (function () { + function C() { + } + Object.defineProperty(C.prototype, "y", { + get: function () { return this.x; }, + set: function (x) { this.y = this.x; }, + enumerable: true, + configurable: true + }); + C.prototype.foo = function () { return this.foo; }; + Object.defineProperty(C, "y", { + get: function () { return this.x; }, + set: function (x) { this.y = this.x; }, + enumerable: true, + configurable: true + }); + C.foo = function () { return this.foo; }; + C.bar = function () { this.foo(); }; + C.prototype.bar = function () { + var C2 = (function () { + function C2() { + } + C2.prototype.foo = function () { + var x; + var x1 = x.foo; + var x2 = x.bar; + var x3 = x.x; + var x4 = x.y; + var sx1 = C.x; + var sx2 = C.y; + var sx3 = C.bar; + var sx4 = C.foo; + var y = new C(); + var y1 = y.foo; + var y2 = y.bar; + var y3 = y.x; + var y4 = y.y; + }; + return C2; + }()); + }; + return C; +}()); diff --git a/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedClass.symbols b/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedClass.symbols new file mode 100644 index 00000000000..8b05cc017c8 --- /dev/null +++ b/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedClass.symbols @@ -0,0 +1,154 @@ +=== tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedClass.ts === +// no errors + +class C { +>C : Symbol(C, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) + + protected x: string; +>x : Symbol(C.x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 2, 9)) + + protected get y() { return this.x; } +>y : Symbol(C.y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 3, 24), Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 4, 40)) +>this.x : Symbol(C.x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 2, 9)) +>this : Symbol(C, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>x : Symbol(C.x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 2, 9)) + + protected set y(x) { this.y = this.x; } +>y : Symbol(C.y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 3, 24), Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 4, 40)) +>x : Symbol(x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 5, 20)) +>this.y : Symbol(C.y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 3, 24), Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 4, 40)) +>this : Symbol(C, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>y : Symbol(C.y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 3, 24), Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 4, 40)) +>this.x : Symbol(C.x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 2, 9)) +>this : Symbol(C, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>x : Symbol(C.x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 2, 9)) + + protected foo() { return this.foo; } +>foo : Symbol(C.foo, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 5, 43)) +>this.foo : Symbol(C.foo, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 5, 43)) +>this : Symbol(C, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>foo : Symbol(C.foo, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 5, 43)) + + protected static x: string; +>x : Symbol(C.x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 6, 40)) + + protected static get y() { return this.x; } +>y : Symbol(C.y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 8, 31), Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 9, 47)) +>this.x : Symbol(C.x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 6, 40)) +>this : Symbol(C, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>x : Symbol(C.x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 6, 40)) + + protected static set y(x) { this.y = this.x; } +>y : Symbol(C.y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 8, 31), Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 9, 47)) +>x : Symbol(x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 10, 27)) +>this.y : Symbol(C.y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 8, 31), Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 9, 47)) +>this : Symbol(C, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>y : Symbol(C.y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 8, 31), Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 9, 47)) +>this.x : Symbol(C.x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 6, 40)) +>this : Symbol(C, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>x : Symbol(C.x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 6, 40)) + + protected static foo() { return this.foo; } +>foo : Symbol(C.foo, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 10, 50)) +>this.foo : Symbol(C.foo, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 10, 50)) +>this : Symbol(C, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>foo : Symbol(C.foo, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 10, 50)) + + protected static bar() { this.foo(); } +>bar : Symbol(C.bar, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 11, 47)) +>this.foo : Symbol(C.foo, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 10, 50)) +>this : Symbol(C, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>foo : Symbol(C.foo, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 10, 50)) + + protected bar() { +>bar : Symbol(C.bar, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 12, 42)) + + class C2 { +>C2 : Symbol(C2, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 14, 21)) + + protected foo() { +>foo : Symbol(C2.foo, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 15, 18)) + + let x: C; +>x : Symbol(x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 17, 19)) +>C : Symbol(C, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) + + var x1 = x.foo; +>x1 : Symbol(x1, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 18, 19)) +>x.foo : Symbol(C.foo, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 5, 43)) +>x : Symbol(x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 17, 19)) +>foo : Symbol(C.foo, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 5, 43)) + + var x2 = x.bar; +>x2 : Symbol(x2, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 19, 19)) +>x.bar : Symbol(C.bar, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 12, 42)) +>x : Symbol(x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 17, 19)) +>bar : Symbol(C.bar, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 12, 42)) + + var x3 = x.x; +>x3 : Symbol(x3, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 20, 19)) +>x.x : Symbol(C.x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 2, 9)) +>x : Symbol(x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 17, 19)) +>x : Symbol(C.x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 2, 9)) + + var x4 = x.y; +>x4 : Symbol(x4, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 21, 19)) +>x.y : Symbol(C.y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 3, 24), Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 4, 40)) +>x : Symbol(x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 17, 19)) +>y : Symbol(C.y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 3, 24), Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 4, 40)) + + var sx1 = C.x; +>sx1 : Symbol(sx1, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 23, 19)) +>C.x : Symbol(C.x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 6, 40)) +>C : Symbol(C, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>x : Symbol(C.x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 6, 40)) + + var sx2 = C.y; +>sx2 : Symbol(sx2, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 24, 19)) +>C.y : Symbol(C.y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 8, 31), Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 9, 47)) +>C : Symbol(C, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>y : Symbol(C.y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 8, 31), Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 9, 47)) + + var sx3 = C.bar; +>sx3 : Symbol(sx3, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 25, 19)) +>C.bar : Symbol(C.bar, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 11, 47)) +>C : Symbol(C, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>bar : Symbol(C.bar, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 11, 47)) + + var sx4 = C.foo; +>sx4 : Symbol(sx4, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 26, 19)) +>C.foo : Symbol(C.foo, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 10, 50)) +>C : Symbol(C, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>foo : Symbol(C.foo, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 10, 50)) + + let y = new C(); +>y : Symbol(y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 28, 19)) +>C : Symbol(C, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) + + var y1 = y.foo; +>y1 : Symbol(y1, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 29, 19)) +>y.foo : Symbol(C.foo, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 5, 43)) +>y : Symbol(y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 28, 19)) +>foo : Symbol(C.foo, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 5, 43)) + + var y2 = y.bar; +>y2 : Symbol(y2, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 30, 19)) +>y.bar : Symbol(C.bar, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 12, 42)) +>y : Symbol(y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 28, 19)) +>bar : Symbol(C.bar, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 12, 42)) + + var y3 = y.x; +>y3 : Symbol(y3, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 31, 19)) +>y.x : Symbol(C.x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 2, 9)) +>y : Symbol(y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 28, 19)) +>x : Symbol(C.x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 2, 9)) + + var y4 = y.y; +>y4 : Symbol(y4, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 32, 19)) +>y.y : Symbol(C.y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 3, 24), Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 4, 40)) +>y : Symbol(y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 28, 19)) +>y : Symbol(C.y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 3, 24), Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 4, 40)) + } + } + } +} diff --git a/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedClass.types b/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedClass.types new file mode 100644 index 00000000000..f7cff2e6719 --- /dev/null +++ b/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedClass.types @@ -0,0 +1,158 @@ +=== tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedClass.ts === +// no errors + +class C { +>C : C + + protected x: string; +>x : string + + protected get y() { return this.x; } +>y : string +>this.x : string +>this : this +>x : string + + protected set y(x) { this.y = this.x; } +>y : string +>x : string +>this.y = this.x : string +>this.y : string +>this : this +>y : string +>this.x : string +>this : this +>x : string + + protected foo() { return this.foo; } +>foo : () => any +>this.foo : () => any +>this : this +>foo : () => any + + protected static x: string; +>x : string + + protected static get y() { return this.x; } +>y : string +>this.x : string +>this : typeof C +>x : string + + protected static set y(x) { this.y = this.x; } +>y : string +>x : string +>this.y = this.x : string +>this.y : string +>this : typeof C +>y : string +>this.x : string +>this : typeof C +>x : string + + protected static foo() { return this.foo; } +>foo : () => typeof C.foo +>this.foo : () => typeof C.foo +>this : typeof C +>foo : () => typeof C.foo + + protected static bar() { this.foo(); } +>bar : () => void +>this.foo() : () => typeof C.foo +>this.foo : () => typeof C.foo +>this : typeof C +>foo : () => typeof C.foo + + protected bar() { +>bar : () => void + + class C2 { +>C2 : C2 + + protected foo() { +>foo : () => void + + let x: C; +>x : C +>C : C + + var x1 = x.foo; +>x1 : () => any +>x.foo : () => any +>x : C +>foo : () => any + + var x2 = x.bar; +>x2 : () => void +>x.bar : () => void +>x : C +>bar : () => void + + var x3 = x.x; +>x3 : string +>x.x : string +>x : C +>x : string + + var x4 = x.y; +>x4 : string +>x.y : string +>x : C +>y : string + + var sx1 = C.x; +>sx1 : string +>C.x : string +>C : typeof C +>x : string + + var sx2 = C.y; +>sx2 : string +>C.y : string +>C : typeof C +>y : string + + var sx3 = C.bar; +>sx3 : () => void +>C.bar : () => void +>C : typeof C +>bar : () => void + + var sx4 = C.foo; +>sx4 : () => typeof C.foo +>C.foo : () => typeof C.foo +>C : typeof C +>foo : () => typeof C.foo + + let y = new C(); +>y : C +>new C() : C +>C : typeof C + + var y1 = y.foo; +>y1 : () => any +>y.foo : () => any +>y : C +>foo : () => any + + var y2 = y.bar; +>y2 : () => void +>y.bar : () => void +>y : C +>bar : () => void + + var y3 = y.x; +>y3 : string +>y.x : string +>y : C +>x : string + + var y4 = y.y; +>y4 : string +>y.y : string +>y : C +>y : string + } + } + } +} diff --git a/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedSubclass.errors.txt b/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedSubclass.errors.txt new file mode 100644 index 00000000000..0bf38477f70 --- /dev/null +++ b/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedSubclass.errors.txt @@ -0,0 +1,44 @@ +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass.ts(25,28): error TS2339: Property 'z' does not exist on type 'C'. + + +==== tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass.ts (1 errors) ==== + + class B { + protected x: string; + protected static x: string; + } + + class C extends B { + protected get y() { return this.x; } + protected set y(x) { this.y = this.x; } + protected foo() { return this.x; } + + protected static get y() { return this.x; } + protected static set y(x) { this.y = this.x; } + protected static foo() { return this.x; } + protected static bar() { this.foo(); } + + protected bar() { + class D { + protected foo() { + var c = new C(); + var c1 = c.y; + var c2 = c.x; + var c3 = c.foo; + var c4 = c.bar; + var c5 = c.z; // error + ~ +!!! error TS2339: Property 'z' does not exist on type 'C'. + + var sc1 = C.x; + var sc2 = C.y; + var sc3 = C.foo; + var sc4 = C.bar; + } + } + } + } + + class E extends C { + protected z: string; + } \ No newline at end of file diff --git a/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedSubclass.js b/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedSubclass.js new file mode 100644 index 00000000000..255c05ac3ac --- /dev/null +++ b/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedSubclass.js @@ -0,0 +1,99 @@ +//// [protectedClassPropertyAccessibleWithinNestedSubclass.ts] + +class B { + protected x: string; + protected static x: string; +} + +class C extends B { + protected get y() { return this.x; } + protected set y(x) { this.y = this.x; } + protected foo() { return this.x; } + + protected static get y() { return this.x; } + protected static set y(x) { this.y = this.x; } + protected static foo() { return this.x; } + protected static bar() { this.foo(); } + + protected bar() { + class D { + protected foo() { + var c = new C(); + var c1 = c.y; + var c2 = c.x; + var c3 = c.foo; + var c4 = c.bar; + var c5 = c.z; // error + + var sc1 = C.x; + var sc2 = C.y; + var sc3 = C.foo; + var sc4 = C.bar; + } + } + } +} + +class E extends C { + protected z: string; +} + +//// [protectedClassPropertyAccessibleWithinNestedSubclass.js] +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; +var B = (function () { + function B() { + } + return B; +}()); +var C = (function (_super) { + __extends(C, _super); + function C() { + _super.apply(this, arguments); + } + Object.defineProperty(C.prototype, "y", { + get: function () { return this.x; }, + set: function (x) { this.y = this.x; }, + enumerable: true, + configurable: true + }); + C.prototype.foo = function () { return this.x; }; + Object.defineProperty(C, "y", { + get: function () { return this.x; }, + set: function (x) { this.y = this.x; }, + enumerable: true, + configurable: true + }); + C.foo = function () { return this.x; }; + C.bar = function () { this.foo(); }; + C.prototype.bar = function () { + var D = (function () { + function D() { + } + D.prototype.foo = function () { + var c = new C(); + var c1 = c.y; + var c2 = c.x; + var c3 = c.foo; + var c4 = c.bar; + var c5 = c.z; // error + var sc1 = C.x; + var sc2 = C.y; + var sc3 = C.foo; + var sc4 = C.bar; + }; + return D; + }()); + }; + return C; +}(B)); +var E = (function (_super) { + __extends(E, _super); + function E() { + _super.apply(this, arguments); + } + return E; +}(C)); diff --git a/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedSubclass1.errors.txt b/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedSubclass1.errors.txt new file mode 100644 index 00000000000..2d882681d72 --- /dev/null +++ b/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedSubclass1.errors.txt @@ -0,0 +1,180 @@ +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(15,20): error TS2445: Property 'x' is protected and only accessible within class 'Derived3' and its subclasses. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(32,19): error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived1'. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(34,20): error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived1'. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(35,20): error TS2445: Property 'x' is protected and only accessible within class 'Derived3' and its subclasses. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(36,20): error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived1'. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(52,19): error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived2'. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(53,20): error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived2'. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(55,20): error TS2445: Property 'x' is protected and only accessible within class 'Derived3' and its subclasses. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(73,19): error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived3'. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(74,20): error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived3'. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(75,20): error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived3'. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(77,20): error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived3'. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(93,19): error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived4'. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(94,20): error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived4'. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(95,20): error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived4'. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(96,20): error TS2445: Property 'x' is protected and only accessible within class 'Derived3' and its subclasses. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(110,3): error TS2445: Property 'x' is protected and only accessible within class 'Base' and its subclasses. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(111,4): error TS2445: Property 'x' is protected and only accessible within class 'Base' and its subclasses. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(112,4): error TS2445: Property 'x' is protected and only accessible within class 'Base' and its subclasses. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(113,4): error TS2445: Property 'x' is protected and only accessible within class 'Derived3' and its subclasses. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(114,4): error TS2445: Property 'x' is protected and only accessible within class 'Base' and its subclasses. + + +==== tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts (21 errors) ==== + class Base { + protected x: string; + method() { + class A { + methoda() { + var b: Base; + var d1: Derived1; + var d2: Derived2; + var d3: Derived3; + var d4: Derived4; + + b.x; // OK, accessed within their declaring class + d1.x; // OK, accessed within their declaring class + d2.x; // OK, accessed within their declaring class + d3.x; // Error, redefined in a subclass, can only be accessed in the declaring class or one of its subclasses + ~ +!!! error TS2445: Property 'x' is protected and only accessible within class 'Derived3' and its subclasses. + d4.x; // OK, accessed within their declaring class + } + } + } + } + + class Derived1 extends Base { + method1() { + class B { + method1b() { + var b: Base; + var d1: Derived1; + var d2: Derived2; + var d3: Derived3; + var d4: Derived4; + + b.x; // Error, isn't accessed through an instance of the enclosing class + ~ +!!! error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived1'. + d1.x; // OK, accessed within a class derived from their declaring class, and through an instance of the enclosing class + d2.x; // Error, isn't accessed through an instance of the enclosing class + ~ +!!! error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived1'. + d3.x; // Error, redefined in a subclass, can only be accessed in the declaring class or one of its subclasses + ~ +!!! error TS2445: Property 'x' is protected and only accessible within class 'Derived3' and its subclasses. + d4.x; // Error, isn't accessed through an instance of the enclosing class + ~ +!!! error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived1'. + } + } + } + } + + class Derived2 extends Base { + method2() { + class C { + method2c() { + var b: Base; + var d1: Derived1; + var d2: Derived2; + var d3: Derived3; + var d4: Derived4; + + b.x; // Error, isn't accessed through an instance of the enclosing class + ~ +!!! error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived2'. + d1.x; // Error, isn't accessed through an instance of the enclosing class + ~ +!!! error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived2'. + d2.x; // OK, accessed within a class derived from their declaring class, and through an instance of the enclosing class + d3.x; // Error, redefined in a subclass, can only be accessed in the declaring class or one of its subclasses + ~ +!!! error TS2445: Property 'x' is protected and only accessible within class 'Derived3' and its subclasses. + d4.x; // OK, accessed within a class derived from their declaring class, and through an instance of the enclosing class or one of its subclasses + } + } + } + } + + class Derived3 extends Derived1 { + protected x: string; + method3() { + class D { + method3d() { + var b: Base; + var d1: Derived1; + var d2: Derived2; + var d3: Derived3; + var d4: Derived4; + + b.x; // Error, isn't accessed through an instance of the enclosing class + ~ +!!! error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived3'. + d1.x; // Error, isn't accessed through an instance of the enclosing class + ~ +!!! error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived3'. + d2.x; // Error, isn't accessed through an instance of the enclosing class + ~ +!!! error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived3'. + d3.x; // OK, accessed within their declaring class + d4.x; // Error, isn't accessed through an instance of the enclosing class + ~ +!!! error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived3'. + } + } + } + } + + class Derived4 extends Derived2 { + method4() { + class E { + method4e() { + var b: Base; + var d1: Derived1; + var d2: Derived2; + var d3: Derived3; + var d4: Derived4; + + b.x; // Error, isn't accessed through an instance of the enclosing class + ~ +!!! error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived4'. + d1.x; // Error, isn't accessed through an instance of the enclosing class + ~ +!!! error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived4'. + d2.x; // Error, isn't accessed through an instance of the enclosing class + ~ +!!! error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived4'. + d3.x; // Error, redefined in a subclass, can only be accessed in the declaring class or one of its subclasses + ~ +!!! error TS2445: Property 'x' is protected and only accessible within class 'Derived3' and its subclasses. + d4.x; // OK, accessed within a class derived from their declaring class, and through an instance of the enclosing class + } + } + } + } + + + var b: Base; + var d1: Derived1; + var d2: Derived2; + var d3: Derived3; + var d4: Derived4; + + b.x; // Error, neither within their declaring class nor classes derived from their declaring class + ~ +!!! error TS2445: Property 'x' is protected and only accessible within class 'Base' and its subclasses. + d1.x; // Error, neither within their declaring class nor classes derived from their declaring class + ~ +!!! error TS2445: Property 'x' is protected and only accessible within class 'Base' and its subclasses. + d2.x; // Error, neither within their declaring class nor classes derived from their declaring class + ~ +!!! error TS2445: Property 'x' is protected and only accessible within class 'Base' and its subclasses. + d3.x; // Error, neither within their declaring class nor classes derived from their declaring class + ~ +!!! error TS2445: Property 'x' is protected and only accessible within class 'Derived3' and its subclasses. + d4.x; // Error, neither within their declaring class nor classes derived from their declaring class + ~ +!!! error TS2445: Property 'x' is protected and only accessible within class 'Base' and its subclasses. \ No newline at end of file diff --git a/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedSubclass1.js b/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedSubclass1.js new file mode 100644 index 00000000000..02ad29bd312 --- /dev/null +++ b/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedSubclass1.js @@ -0,0 +1,260 @@ +//// [protectedClassPropertyAccessibleWithinNestedSubclass1.ts] +class Base { + protected x: string; + method() { + class A { + methoda() { + var b: Base; + var d1: Derived1; + var d2: Derived2; + var d3: Derived3; + var d4: Derived4; + + b.x; // OK, accessed within their declaring class + d1.x; // OK, accessed within their declaring class + d2.x; // OK, accessed within their declaring class + d3.x; // Error, redefined in a subclass, can only be accessed in the declaring class or one of its subclasses + d4.x; // OK, accessed within their declaring class + } + } + } +} + +class Derived1 extends Base { + method1() { + class B { + method1b() { + var b: Base; + var d1: Derived1; + var d2: Derived2; + var d3: Derived3; + var d4: Derived4; + + b.x; // Error, isn't accessed through an instance of the enclosing class + d1.x; // OK, accessed within a class derived from their declaring class, and through an instance of the enclosing class + d2.x; // Error, isn't accessed through an instance of the enclosing class + d3.x; // Error, redefined in a subclass, can only be accessed in the declaring class or one of its subclasses + d4.x; // Error, isn't accessed through an instance of the enclosing class + } + } + } +} + +class Derived2 extends Base { + method2() { + class C { + method2c() { + var b: Base; + var d1: Derived1; + var d2: Derived2; + var d3: Derived3; + var d4: Derived4; + + b.x; // Error, isn't accessed through an instance of the enclosing class + d1.x; // Error, isn't accessed through an instance of the enclosing class + d2.x; // OK, accessed within a class derived from their declaring class, and through an instance of the enclosing class + d3.x; // Error, redefined in a subclass, can only be accessed in the declaring class or one of its subclasses + d4.x; // OK, accessed within a class derived from their declaring class, and through an instance of the enclosing class or one of its subclasses + } + } + } +} + +class Derived3 extends Derived1 { + protected x: string; + method3() { + class D { + method3d() { + var b: Base; + var d1: Derived1; + var d2: Derived2; + var d3: Derived3; + var d4: Derived4; + + b.x; // Error, isn't accessed through an instance of the enclosing class + d1.x; // Error, isn't accessed through an instance of the enclosing class + d2.x; // Error, isn't accessed through an instance of the enclosing class + d3.x; // OK, accessed within their declaring class + d4.x; // Error, isn't accessed through an instance of the enclosing class + } + } + } +} + +class Derived4 extends Derived2 { + method4() { + class E { + method4e() { + var b: Base; + var d1: Derived1; + var d2: Derived2; + var d3: Derived3; + var d4: Derived4; + + b.x; // Error, isn't accessed through an instance of the enclosing class + d1.x; // Error, isn't accessed through an instance of the enclosing class + d2.x; // Error, isn't accessed through an instance of the enclosing class + d3.x; // Error, redefined in a subclass, can only be accessed in the declaring class or one of its subclasses + d4.x; // OK, accessed within a class derived from their declaring class, and through an instance of the enclosing class + } + } + } +} + + +var b: Base; +var d1: Derived1; +var d2: Derived2; +var d3: Derived3; +var d4: Derived4; + +b.x; // Error, neither within their declaring class nor classes derived from their declaring class +d1.x; // Error, neither within their declaring class nor classes derived from their declaring class +d2.x; // Error, neither within their declaring class nor classes derived from their declaring class +d3.x; // Error, neither within their declaring class nor classes derived from their declaring class +d4.x; // Error, neither within their declaring class nor classes derived from their declaring class + +//// [protectedClassPropertyAccessibleWithinNestedSubclass1.js] +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; +var Base = (function () { + function Base() { + } + Base.prototype.method = function () { + var A = (function () { + function A() { + } + A.prototype.methoda = function () { + var b; + var d1; + var d2; + var d3; + var d4; + b.x; // OK, accessed within their declaring class + d1.x; // OK, accessed within their declaring class + d2.x; // OK, accessed within their declaring class + d3.x; // Error, redefined in a subclass, can only be accessed in the declaring class or one of its subclasses + d4.x; // OK, accessed within their declaring class + }; + return A; + }()); + }; + return Base; +}()); +var Derived1 = (function (_super) { + __extends(Derived1, _super); + function Derived1() { + _super.apply(this, arguments); + } + Derived1.prototype.method1 = function () { + var B = (function () { + function B() { + } + B.prototype.method1b = function () { + var b; + var d1; + var d2; + var d3; + var d4; + b.x; // Error, isn't accessed through an instance of the enclosing class + d1.x; // OK, accessed within a class derived from their declaring class, and through an instance of the enclosing class + d2.x; // Error, isn't accessed through an instance of the enclosing class + d3.x; // Error, redefined in a subclass, can only be accessed in the declaring class or one of its subclasses + d4.x; // Error, isn't accessed through an instance of the enclosing class + }; + return B; + }()); + }; + return Derived1; +}(Base)); +var Derived2 = (function (_super) { + __extends(Derived2, _super); + function Derived2() { + _super.apply(this, arguments); + } + Derived2.prototype.method2 = function () { + var C = (function () { + function C() { + } + C.prototype.method2c = function () { + var b; + var d1; + var d2; + var d3; + var d4; + b.x; // Error, isn't accessed through an instance of the enclosing class + d1.x; // Error, isn't accessed through an instance of the enclosing class + d2.x; // OK, accessed within a class derived from their declaring class, and through an instance of the enclosing class + d3.x; // Error, redefined in a subclass, can only be accessed in the declaring class or one of its subclasses + d4.x; // OK, accessed within a class derived from their declaring class, and through an instance of the enclosing class or one of its subclasses + }; + return C; + }()); + }; + return Derived2; +}(Base)); +var Derived3 = (function (_super) { + __extends(Derived3, _super); + function Derived3() { + _super.apply(this, arguments); + } + Derived3.prototype.method3 = function () { + var D = (function () { + function D() { + } + D.prototype.method3d = function () { + var b; + var d1; + var d2; + var d3; + var d4; + b.x; // Error, isn't accessed through an instance of the enclosing class + d1.x; // Error, isn't accessed through an instance of the enclosing class + d2.x; // Error, isn't accessed through an instance of the enclosing class + d3.x; // OK, accessed within their declaring class + d4.x; // Error, isn't accessed through an instance of the enclosing class + }; + return D; + }()); + }; + return Derived3; +}(Derived1)); +var Derived4 = (function (_super) { + __extends(Derived4, _super); + function Derived4() { + _super.apply(this, arguments); + } + Derived4.prototype.method4 = function () { + var E = (function () { + function E() { + } + E.prototype.method4e = function () { + var b; + var d1; + var d2; + var d3; + var d4; + b.x; // Error, isn't accessed through an instance of the enclosing class + d1.x; // Error, isn't accessed through an instance of the enclosing class + d2.x; // Error, isn't accessed through an instance of the enclosing class + d3.x; // Error, redefined in a subclass, can only be accessed in the declaring class or one of its subclasses + d4.x; // OK, accessed within a class derived from their declaring class, and through an instance of the enclosing class + }; + return E; + }()); + }; + return Derived4; +}(Derived2)); +var b; +var d1; +var d2; +var d3; +var d4; +b.x; // Error, neither within their declaring class nor classes derived from their declaring class +d1.x; // Error, neither within their declaring class nor classes derived from their declaring class +d2.x; // Error, neither within their declaring class nor classes derived from their declaring class +d3.x; // Error, neither within their declaring class nor classes derived from their declaring class +d4.x; // Error, neither within their declaring class nor classes derived from their declaring class diff --git a/tests/baselines/reference/reactNamespaceJSXEmit.symbols b/tests/baselines/reference/reactNamespaceJSXEmit.symbols index a0012cfd07a..3ca5b91e538 100644 --- a/tests/baselines/reference/reactNamespaceJSXEmit.symbols +++ b/tests/baselines/reference/reactNamespaceJSXEmit.symbols @@ -17,6 +17,7 @@ declare var x: any; >data : Symbol(unknown) ; +>Bar : Symbol(Bar, Decl(reactNamespaceJSXEmit.tsx, 3, 11)) >x : Symbol(unknown) >x : Symbol(x, Decl(reactNamespaceJSXEmit.tsx, 4, 11)) @@ -24,9 +25,11 @@ declare var x: any; >x-component : Symbol(unknown) ; +>Bar : Symbol(Bar, Decl(reactNamespaceJSXEmit.tsx, 3, 11)) >x : Symbol(x, Decl(reactNamespaceJSXEmit.tsx, 4, 11)) ; +>Bar : Symbol(Bar, Decl(reactNamespaceJSXEmit.tsx, 3, 11)) >x : Symbol(x, Decl(reactNamespaceJSXEmit.tsx, 4, 11)) >y : Symbol(unknown) diff --git a/tests/baselines/reference/stringLiteralTypesWithVariousOperators02.errors.txt b/tests/baselines/reference/stringLiteralTypesWithVariousOperators02.errors.txt index 69dd6c2f6a9..92afe67df0c 100644 --- a/tests/baselines/reference/stringLiteralTypesWithVariousOperators02.errors.txt +++ b/tests/baselines/reference/stringLiteralTypesWithVariousOperators02.errors.txt @@ -7,9 +7,12 @@ tests/cases/conformance/types/stringLiteral/stringLiteralTypesWithVariousOperato tests/cases/conformance/types/stringLiteral/stringLiteralTypesWithVariousOperators02.ts(13,11): error TS2356: An arithmetic operand must be of type 'any', 'number' or an enum type. tests/cases/conformance/types/stringLiteral/stringLiteralTypesWithVariousOperators02.ts(14,9): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type. tests/cases/conformance/types/stringLiteral/stringLiteralTypesWithVariousOperators02.ts(15,9): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type. +tests/cases/conformance/types/stringLiteral/stringLiteralTypesWithVariousOperators02.ts(16,9): error TS2365: Operator '<' cannot be applied to types '"ABC"' and '"XYZ"'. +tests/cases/conformance/types/stringLiteral/stringLiteralTypesWithVariousOperators02.ts(17,9): error TS2365: Operator '===' cannot be applied to types '"ABC"' and '"XYZ"'. +tests/cases/conformance/types/stringLiteral/stringLiteralTypesWithVariousOperators02.ts(18,9): error TS2365: Operator '!=' cannot be applied to types '"ABC"' and '"XYZ"'. -==== tests/cases/conformance/types/stringLiteral/stringLiteralTypesWithVariousOperators02.ts (9 errors) ==== +==== tests/cases/conformance/types/stringLiteral/stringLiteralTypesWithVariousOperators02.ts (12 errors) ==== let abc: "ABC" = "ABC"; let xyz: "XYZ" = "XYZ"; @@ -44,5 +47,11 @@ tests/cases/conformance/types/stringLiteral/stringLiteralTypesWithVariousOperato ~~~~~~~~~~~~~~~~ !!! error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type. let j = abc < xyz; + ~~~~~~~~~ +!!! error TS2365: Operator '<' cannot be applied to types '"ABC"' and '"XYZ"'. let k = abc === xyz; - let l = abc != xyz; \ No newline at end of file + ~~~~~~~~~~~ +!!! error TS2365: Operator '===' cannot be applied to types '"ABC"' and '"XYZ"'. + let l = abc != xyz; + ~~~~~~~~~~ +!!! error TS2365: Operator '!=' cannot be applied to types '"ABC"' and '"XYZ"'. \ No newline at end of file diff --git a/tests/baselines/reference/tsxAttributeResolution13.types b/tests/baselines/reference/tsxAttributeResolution13.types index f0435b80812..1a426d86e7d 100644 --- a/tests/baselines/reference/tsxAttributeResolution13.types +++ b/tests/baselines/reference/tsxAttributeResolution13.types @@ -5,6 +5,6 @@ function Test() { } > : any ->Test : any ->Test : any +>Test : () => void +>Test : () => void diff --git a/tests/baselines/reference/tsxElementResolution.symbols b/tests/baselines/reference/tsxElementResolution.symbols index e9756e9efc9..cd7ac7807f1 100644 --- a/tests/baselines/reference/tsxElementResolution.symbols +++ b/tests/baselines/reference/tsxElementResolution.symbols @@ -47,5 +47,7 @@ var d = ; var e = ; >e : Symbol(e, Decl(tsxElementResolution.tsx, 23, 3)) +>Dotted.Name : Symbol(Dotted.Name, Decl(tsxElementResolution.tsx, 12, 15)) +>Dotted : Symbol(Dotted, Decl(tsxElementResolution.tsx, 10, 14)) >Name : Symbol(Dotted.Name, Decl(tsxElementResolution.tsx, 12, 15)) diff --git a/tests/baselines/reference/tsxElementResolution.types b/tests/baselines/reference/tsxElementResolution.types index 89600bbbc2f..a1c2abcef7c 100644 --- a/tests/baselines/reference/tsxElementResolution.types +++ b/tests/baselines/reference/tsxElementResolution.types @@ -51,6 +51,7 @@ var d = ; var e = ; >e : any > : any ->Dotted : any ->Name : any +>Dotted.Name : typeof Dotted.Name +>Dotted : typeof Dotted +>Name : typeof Dotted.Name diff --git a/tests/baselines/reference/tsxElementResolution17.symbols b/tests/baselines/reference/tsxElementResolution17.symbols index 0b4459552de..0225cc35d91 100644 --- a/tests/baselines/reference/tsxElementResolution17.symbols +++ b/tests/baselines/reference/tsxElementResolution17.symbols @@ -8,6 +8,8 @@ import s2 = require('elements2'); >s2 : Symbol(s2, Decl(consumer.tsx, 2, 33)) ; +>s1.MyElement : Symbol(s1.MyElement, Decl(file.tsx, 6, 28)) +>s1 : Symbol(s1, Decl(consumer.tsx, 0, 0)) >MyElement : Symbol(s1.MyElement, Decl(file.tsx, 6, 28)) === tests/cases/conformance/jsx/file.tsx === diff --git a/tests/baselines/reference/tsxElementResolution17.types b/tests/baselines/reference/tsxElementResolution17.types index e6396a9a60b..c68c19f58e7 100644 --- a/tests/baselines/reference/tsxElementResolution17.types +++ b/tests/baselines/reference/tsxElementResolution17.types @@ -9,8 +9,9 @@ import s2 = require('elements2'); ; > : JSX.Element ->s1 : any ->MyElement : any +>s1.MyElement : typeof s1.MyElement +>s1 : typeof s1 +>MyElement : typeof s1.MyElement === tests/cases/conformance/jsx/file.tsx === diff --git a/tests/baselines/reference/tsxElementResolution19.symbols b/tests/baselines/reference/tsxElementResolution19.symbols index 87c48ccedf0..48aa4f962b6 100644 --- a/tests/baselines/reference/tsxElementResolution19.symbols +++ b/tests/baselines/reference/tsxElementResolution19.symbols @@ -24,5 +24,5 @@ import {MyClass} from './file1'; >MyClass : Symbol(MyClass, Decl(file2.tsx, 3, 8)) ; ->MyClass : Symbol(MyClass, Decl(file1.tsx, 2, 1)) +>MyClass : Symbol(MyClass, Decl(file2.tsx, 3, 8)) diff --git a/tests/baselines/reference/tsxEmit3.symbols b/tests/baselines/reference/tsxEmit3.symbols index 3b88d4e0371..3eb4ef3b05d 100644 --- a/tests/baselines/reference/tsxEmit3.symbols +++ b/tests/baselines/reference/tsxEmit3.symbols @@ -59,6 +59,8 @@ module M { >S.Bar : Symbol(S.Bar, Decl(file.tsx, 8, 18)) >S : Symbol(S, Decl(file.tsx, 7, 39), Decl(file.tsx, 18, 14)) >Bar : Symbol(S.Bar, Decl(file.tsx, 8, 18)) +>S.Bar : Symbol(S.Bar, Decl(file.tsx, 8, 18)) +>S : Symbol(S, Decl(file.tsx, 7, 39), Decl(file.tsx, 18, 14)) >Bar : Symbol(S.Bar, Decl(file.tsx, 8, 18)) } diff --git a/tests/baselines/reference/tsxEmit3.types b/tests/baselines/reference/tsxEmit3.types index 49a5cf8a51b..e70c44d0041 100644 --- a/tests/baselines/reference/tsxEmit3.types +++ b/tests/baselines/reference/tsxEmit3.types @@ -67,8 +67,9 @@ module M { >S : typeof S >Bar : typeof S.Bar > : JSX.Element ->S : any ->Bar : any +>S.Bar : typeof S.Bar +>S : typeof S +>Bar : typeof S.Bar } module M { diff --git a/tests/baselines/reference/tsxExternalModuleEmit1.symbols b/tests/baselines/reference/tsxExternalModuleEmit1.symbols index 261a9035216..e2d3eee98b0 100644 --- a/tests/baselines/reference/tsxExternalModuleEmit1.symbols +++ b/tests/baselines/reference/tsxExternalModuleEmit1.symbols @@ -25,7 +25,7 @@ export class App extends React.Component { >render : Symbol(App.render, Decl(app.tsx, 5, 52)) return