diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a952f5a7c95..903d18e2331 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -132,6 +132,7 @@ namespace ts { const esSymbolType = createIntrinsicType(TypeFlags.ESSymbol, "symbol"); const voidType = createIntrinsicType(TypeFlags.Void, "void"); const neverType = createIntrinsicType(TypeFlags.Never, "never"); + const silentNeverType = createIntrinsicType(TypeFlags.Never, "never"); const emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); const emptyGenericType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); @@ -147,6 +148,7 @@ namespace ts { const anySignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); const unknownSignature = createSignature(undefined, undefined, undefined, emptyArray, unknownType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); const resolvingSignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); + const silentNeverSignature = createSignature(undefined, undefined, undefined, emptyArray, silentNeverType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); const enumNumberIndexInfo = createIndexInfo(stringType, /*isReadonly*/ true); @@ -6504,6 +6506,9 @@ namespace ts { } else if (source.symbol && source.flags & TypeFlags.ObjectType && globalObjectType === source) { reportError(Diagnostics.The_Object_type_is_assignable_to_very_few_other_types_Did_you_mean_to_use_the_any_type_instead); } + else if (source.symbol && source.flags & TypeFlags.ObjectType && globalObjectType === source) { + reportError(Diagnostics.The_Object_type_is_assignable_to_very_few_other_types_Did_you_mean_to_use_the_any_type_instead); + } reportRelationError(headMessage, source, target); } return Ternary.False; @@ -8072,8 +8077,11 @@ namespace ts { // we remove type string. function getAssignmentReducedType(declaredType: UnionType, assignedType: Type) { if (declaredType !== assignedType) { + if (assignedType.flags & TypeFlags.Never) { + return assignedType; + } const reducedType = filterType(declaredType, t => typeMaybeAssignableTo(assignedType, t)); - if (reducedType !== neverType) { + if (!(reducedType.flags & TypeFlags.Never)) { return reducedType; } } @@ -8353,7 +8361,7 @@ namespace ts { const visitedFlowStart = visitedFlowCount; const result = getTypeFromFlowType(getTypeAtFlowNode(reference.flowNode)); visitedFlowCount = visitedFlowStart; - if (reference.parent.kind === SyntaxKind.NonNullExpression && getTypeWithFacts(result, TypeFacts.NEUndefinedOrNull) === neverType) { + if (reference.parent.kind === SyntaxKind.NonNullExpression && getTypeWithFacts(result, TypeFacts.NEUndefinedOrNull).flags & TypeFlags.Never) { return declaredType; } return result; @@ -8442,17 +8450,18 @@ namespace ts { function getTypeAtFlowCondition(flow: FlowCondition): FlowType { const flowType = getTypeAtFlowNode(flow.antecedent); let type = getTypeFromFlowType(flowType); - if (type !== neverType) { + if (!(type.flags & TypeFlags.Never)) { // If we have an antecedent type (meaning we're reachable in some way), we first // attempt to narrow the antecedent type. If that produces the never type, and if // the antecedent type is incomplete (i.e. a transient type in a loop), then we // take the type guard as an indication that control *could* reach here once we - // have the complete type. We proceed by reverting to the declared type and then - // narrow that. + // have the complete type. We proceed by switching to the silent never type which + // doesn't report errors when operators are applied to it. Note that this is the + // *only* place a silent never type is ever generated. const assumeTrue = (flow.flags & FlowFlags.TrueCondition) !== 0; type = narrowType(type, flow.expression, assumeTrue); - if (type === neverType && isIncomplete(flowType)) { - type = narrowType(declaredType, flow.expression, assumeTrue); + if (type.flags & TypeFlags.Never && isIncomplete(flowType)) { + type = silentNeverType; } } return createFlowType(type, isIncomplete(flowType)); @@ -8661,7 +8670,7 @@ namespace ts { } if (assumeTrue) { const narrowedType = filterType(type, t => areTypesComparable(t, valueType)); - return narrowedType !== neverType ? narrowedType : type; + return narrowedType.flags & TypeFlags.Never ? type : narrowedType; } return isUnitType(valueType) ? filterType(type, t => t !== valueType) : type; } @@ -8704,12 +8713,12 @@ namespace ts { const clauseTypes = switchTypes.slice(clauseStart, clauseEnd); const hasDefaultClause = clauseStart === clauseEnd || contains(clauseTypes, neverType); const discriminantType = getUnionType(clauseTypes); - const caseType = discriminantType === neverType ? neverType : filterType(type, t => isTypeComparableTo(discriminantType, t)); + const caseType = discriminantType.flags & TypeFlags.Never ? neverType : filterType(type, t => isTypeComparableTo(discriminantType, t)); if (!hasDefaultClause) { return caseType; } const defaultType = filterType(type, t => !(isUnitType(t) && contains(switchTypes, t))); - return caseType === neverType ? defaultType : getUnionType([caseType, defaultType]); + return caseType.flags & TypeFlags.Never ? defaultType : getUnionType([caseType, defaultType]); } function narrowTypeByInstanceof(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type { @@ -8773,7 +8782,7 @@ namespace ts { // the candidate type. If one or more constituents remain, return a union of those. if (type.flags & TypeFlags.Union) { const assignableType = filterType(type, t => isTypeInstanceOf(t, candidate)); - if (assignableType !== neverType) { + if (!(assignableType.flags & TypeFlags.Never)) { return assignableType; } } @@ -10891,7 +10900,7 @@ namespace ts { function checkPropertyAccessExpressionOrQualifiedName(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, right: Identifier) { const type = checkNonNullExpression(left); - if (isTypeAny(type)) { + if (isTypeAny(type) || type === silentNeverType) { return type; } @@ -11038,8 +11047,8 @@ namespace ts { const objectType = getApparentType(checkNonNullExpression(node.expression)); const indexType = node.argumentExpression ? checkExpression(node.argumentExpression) : unknownType; - if (objectType === unknownType) { - return unknownType; + if (objectType === unknownType || objectType === silentNeverType) { + return objectType; } const isConstEnum = isConstEnumObjectType(objectType); @@ -12089,6 +12098,9 @@ namespace ts { } const funcType = checkNonNullExpression(node.expression); + if (funcType === silentNeverType) { + return silentNeverSignature; + } const apparentType = getApparentType(funcType); if (apparentType === unknownType) { @@ -12161,6 +12173,9 @@ namespace ts { } let expressionType = checkNonNullExpression(node.expression); + if (expressionType === silentNeverType) { + return silentNeverSignature; + } // 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 @@ -12720,7 +12735,7 @@ namespace ts { // the native Promise type by the caller. type = checkAwaitedType(type, func, Diagnostics.Return_expression_in_async_function_does_not_have_a_valid_callable_then_member); } - if (type === neverType) { + if (type.flags & TypeFlags.Never) { hasReturnOfTypeNever = true; } else if (!contains(aggregatedTypes, type)) { @@ -12770,7 +12785,7 @@ namespace ts { const hasExplicitReturn = func.flags & NodeFlags.HasExplicitReturn; - if (returnType === neverType) { + if (returnType && returnType.flags & TypeFlags.Never) { error(func.type, Diagnostics.A_function_returning_never_cannot_have_a_reachable_end_point); } else if (returnType && !hasExplicitReturn) { @@ -13026,6 +13041,9 @@ namespace ts { function checkPrefixUnaryExpression(node: PrefixUnaryExpression): Type { const operandType = checkExpression(node.operand); + if (operandType === silentNeverType) { + return silentNeverType; + } if (node.operator === SyntaxKind.MinusToken && node.operand.kind === SyntaxKind.NumericLiteral) { return getLiteralTypeForText(TypeFlags.NumberLiteral, "" + -(node.operand).text); } @@ -13059,6 +13077,9 @@ namespace ts { function checkPostfixUnaryExpression(node: PostfixUnaryExpression): Type { const operandType = checkExpression(node.operand); + if (operandType === silentNeverType) { + return silentNeverType; + } const ok = checkArithmeticOperandType(node.operand, getNonNullableType(operandType), Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type); if (ok) { @@ -13123,6 +13144,9 @@ namespace ts { } function checkInstanceOfExpression(left: Expression, right: Expression, leftType: Type, rightType: Type): Type { + if (leftType === silentNeverType || rightType === silentNeverType) { + return silentNeverType; + } // TypeScript 1.0 spec (April 2014): 4.15.4 // The instanceof operator requires the left operand to be of type Any, an object type, or a type parameter type, // and the right operand to be of type Any or a subtype of the 'Function' interface type. @@ -13139,6 +13163,9 @@ namespace ts { } function checkInExpression(left: Expression, right: Expression, leftType: Type, rightType: Type): Type { + if (leftType === silentNeverType || rightType === silentNeverType) { + return silentNeverType; + } // TypeScript 1.0 spec (April 2014): 4.15.5 // The in operator requires the left operand to be of type Any, the String primitive type, or the Number primitive type, // and the right operand to be of type Any, an object type, or a type parameter type. @@ -13403,6 +13430,9 @@ namespace ts { case SyntaxKind.CaretEqualsToken: case SyntaxKind.AmpersandToken: case SyntaxKind.AmpersandEqualsToken: + if (leftType === silentNeverType || rightType === silentNeverType) { + return silentNeverType; + } // TypeScript 1.0 spec (April 2014): 4.19.1 // These operators require their operands to be of type Any, the Number primitive type, // or an enum type. Operands of an enum type are treated @@ -13435,6 +13465,9 @@ namespace ts { return numberType; case SyntaxKind.PlusToken: case SyntaxKind.PlusEqualsToken: + if (leftType === silentNeverType || rightType === silentNeverType) { + return silentNeverType; + } // TypeScript 1.0 spec (April 2014): 4.19.2 // The binary + operator requires both operands to be of the Number primitive type or an enum type, // or at least one of the operands to be of type Any or the String primitive type. @@ -16267,7 +16300,7 @@ namespace ts { // Now that we've removed all the StringLike types, if no constituents remain, then the entire // arrayOrStringType was a string. - if (arrayType === neverType) { + if (arrayType.flags & TypeFlags.Never) { return stringType; } } @@ -16328,7 +16361,7 @@ namespace ts { if (func) { const signature = getSignatureFromDeclaration(func); const returnType = getReturnTypeOfSignature(signature); - if (strictNullChecks || node.expression || returnType === neverType) { + if (strictNullChecks || node.expression || returnType.flags & TypeFlags.Never) { const exprType = node.expression ? checkExpressionCached(node.expression) : undefinedType; if (func.asteriskToken) { diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 916d32841a4..b39c017384e 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -667,7 +667,7 @@ namespace ts { } function printHelp() { - let output = ""; + const output: string[] = []; // We want to align our "syntax" and "examples" commands to a certain margin. const syntaxLength = getDiagnosticText(Diagnostics.Syntax_Colon_0, "").length; @@ -678,17 +678,17 @@ namespace ts { let syntax = makePadding(marginLength - syntaxLength); syntax += "tsc [" + getDiagnosticText(Diagnostics.options) + "] [" + getDiagnosticText(Diagnostics.file) + " ...]"; - output += getDiagnosticText(Diagnostics.Syntax_Colon_0, syntax); - output += sys.newLine + sys.newLine; + output.push(getDiagnosticText(Diagnostics.Syntax_Colon_0, syntax)); + output.push(sys.newLine + sys.newLine); // Build up the list of examples. const padding = makePadding(marginLength); - output += getDiagnosticText(Diagnostics.Examples_Colon_0, makePadding(marginLength - examplesLength) + "tsc hello.ts") + sys.newLine; - output += padding + "tsc --outFile file.js file.ts" + sys.newLine; - output += padding + "tsc @args.txt" + sys.newLine; - output += sys.newLine; + output.push(getDiagnosticText(Diagnostics.Examples_Colon_0, makePadding(marginLength - examplesLength) + "tsc hello.ts") + sys.newLine); + output.push(padding + "tsc --outFile file.js file.ts" + sys.newLine); + output.push(padding + "tsc @args.txt" + sys.newLine); + output.push(sys.newLine); - output += getDiagnosticText(Diagnostics.Options_Colon) + sys.newLine; + output.push(getDiagnosticText(Diagnostics.Options_Colon) + sys.newLine); // Sort our options by their names, (e.g. "--noImplicitAny" comes before "--watch") const optsList = filter(optionDeclarations.slice(), v => !v.experimental); @@ -755,18 +755,20 @@ namespace ts { const usage = usageColumn[i]; const description = descriptionColumn[i]; const kindsList = optionsDescriptionMap[description]; - output += usage + makePadding(marginLength - usage.length + 2) + description + sys.newLine; + output.push(usage + makePadding(marginLength - usage.length + 2) + description + sys.newLine); if (kindsList) { - output += makePadding(marginLength + 4); + output.push(makePadding(marginLength + 4)); for (const kind of kindsList) { - output += kind + " "; + output.push(kind + " "); } - output += sys.newLine; + output.push(sys.newLine); } } - sys.write(output); + for (const line of output) { + sys.write(line); + } return; function getParamType(option: CommandLineOption) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index b1b672d015b..e4bc9a29d5b 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1604,7 +1604,7 @@ namespace ts { // @kind(SyntaxKind.JSDocComment) export interface JSDoc extends Node { - tags: NodeArray; + tags: NodeArray | undefined; comment: string | undefined; } diff --git a/src/harness/compilerRunner.ts b/src/harness/compilerRunner.ts index 63e01f0f814..70c6fdac329 100644 --- a/src/harness/compilerRunner.ts +++ b/src/harness/compilerRunner.ts @@ -136,9 +136,7 @@ class CompilerBaselineRunner extends RunnerBase { // check errors it("Correct errors for " + fileName, () => { - if (this.errors) { - Harness.Compiler.doErrorBaseline(justName, toBeCompiled.concat(otherFiles), result.errors); - } + Harness.Compiler.doErrorBaseline(justName, toBeCompiled.concat(otherFiles), result.errors); }); it (`Correct module resolution tracing for ${fileName}`, () => { diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 0863c58851d..b4fd8736b2f 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -1407,7 +1407,7 @@ namespace Harness { export function doErrorBaseline(baselinePath: string, inputFiles: TestFile[], errors: ts.Diagnostic[]) { Harness.Baseline.runBaseline(baselinePath.replace(/\.tsx?$/, ".errors.txt"), (): string => { - if (errors.length === 0) { + if (!errors || (errors.length === 0)) { /* tslint:disable:no-null-keyword */ return null; /* tslint:enable:no-null-keyword */ diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index f96676747e4..a67f68eb1a9 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -492,6 +492,9 @@ namespace Harness.LanguageService { getNonBoundSourceFile(fileName: string): ts.SourceFile { throw new Error("SourceFile can not be marshaled across the shim layer."); } + getSourceFile(fileName: string): ts.SourceFile { + throw new Error("SourceFile can not be marshaled across the shim layer."); + } dispose(): void { this.shim.dispose({}); } } diff --git a/src/lib/es2015.reflect.d.ts b/src/lib/es2015.reflect.d.ts index eda8d352263..2dc92c3bddb 100644 --- a/src/lib/es2015.reflect.d.ts +++ b/src/lib/es2015.reflect.d.ts @@ -6,8 +6,7 @@ declare namespace Reflect { function get(target: any, propertyKey: PropertyKey, receiver?: any): any; function getOwnPropertyDescriptor(target: any, propertyKey: PropertyKey): PropertyDescriptor; function getPrototypeOf(target: any): any; - function has(target: any, propertyKey: string): boolean; - function has(target: any, propertyKey: symbol): boolean; + function has(target: any, propertyKey: PropertyKey): boolean; function isExtensible(target: any): boolean; function ownKeys(target: any): Array; function preventExtensions(target: any): boolean; diff --git a/src/server/client.ts b/src/server/client.ts index 7268c3c9573..5032056c2f3 100644 --- a/src/server/client.ts +++ b/src/server/client.ts @@ -678,6 +678,10 @@ namespace ts.server { throw new Error("SourceFile objects are not serializable through the server protocol."); } + getSourceFile(fileName: string): SourceFile { + throw new Error("SourceFile objects are not serializable through the server protocol."); + } + cleanupSemanticCache(): void { throw new Error("cleanupSemanticCache is not available through the server layer."); } diff --git a/src/services/navigationBar.ts b/src/services/navigationBar.ts index c2a5b745d3a..5c8c47e9666 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -218,15 +218,13 @@ namespace ts.NavigationBar { break; default: - if (node.jsDocComments) { - for (const jsDocComment of node.jsDocComments) { - for (const tag of jsDocComment.tags) { - if (tag.kind === SyntaxKind.JSDocTypedefTag) { - addLeafNode(tag); - } + forEach(node.jsDocComments, jsDocComment => { + forEach(jsDocComment.tags, tag => { + if (tag.kind === SyntaxKind.JSDocTypedefTag) { + addLeafNode(tag); } - } - } + }); + }); forEachChild(node, addChildrenRecursively); } diff --git a/src/services/services.ts b/src/services/services.ts index 67843c1ce50..ad071723083 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1401,6 +1401,10 @@ namespace ts { return syntaxTreeCache.getCurrentSourceFile(fileName); } + function getSourceFile(fileName: string): SourceFile { + return getNonBoundSourceFile(fileName); + } + function getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan { const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); @@ -1812,6 +1816,7 @@ namespace ts { isValidBraceCompletionAtPosition, getEmitOutput, getNonBoundSourceFile, + getSourceFile, getProgram }; } diff --git a/src/services/types.ts b/src/services/types.ts index 7bd325482e6..e8c411cc1c8 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -240,6 +240,12 @@ namespace ts { /* @internal */ getNonBoundSourceFile(fileName: string): SourceFile; + /** + * @internal + * @deprecated Use ts.createSourceFile instead. + */ + getSourceFile(fileName: string): SourceFile; + dispose(): void; } diff --git a/tests/baselines/reference/assigningFromObjectToAnythingElse.errors.txt b/tests/baselines/reference/assigningFromObjectToAnythingElse.errors.txt new file mode 100644 index 00000000000..289883d7471 --- /dev/null +++ b/tests/baselines/reference/assigningFromObjectToAnythingElse.errors.txt @@ -0,0 +1,38 @@ +tests/cases/compiler/assigningFromObjectToAnythingElse.ts(3,1): error TS2322: Type 'Object' is not assignable to type 'RegExp'. + The 'Object' type is assignable to very few other types. Did you mean to use the 'any' type instead? + Property 'exec' is missing in type 'Object'. +tests/cases/compiler/assigningFromObjectToAnythingElse.ts(5,5): error TS2322: Type 'Object' is not assignable to type 'String'. + The 'Object' type is assignable to very few other types. Did you mean to use the 'any' type instead? + Property 'charAt' is missing in type 'Object'. +tests/cases/compiler/assigningFromObjectToAnythingElse.ts(6,5): error TS2322: Type 'Number' is not assignable to type 'String'. + Property 'charAt' is missing in type 'Number'. +tests/cases/compiler/assigningFromObjectToAnythingElse.ts(8,5): error TS2322: Type 'Object' is not assignable to type 'Error'. + The 'Object' type is assignable to very few other types. Did you mean to use the 'any' type instead? + Property 'name' is missing in type 'Object'. + + +==== tests/cases/compiler/assigningFromObjectToAnythingElse.ts (4 errors) ==== + var x: Object; + var y: RegExp; + y = x; + ~ +!!! error TS2322: Type 'Object' is not assignable to type 'RegExp'. +!!! error TS2322: The 'Object' type is assignable to very few other types. Did you mean to use the 'any' type instead? +!!! error TS2322: Property 'exec' is missing in type 'Object'. + + var a: String = Object.create(""); + ~ +!!! error TS2322: Type 'Object' is not assignable to type 'String'. +!!! error TS2322: The 'Object' type is assignable to very few other types. Did you mean to use the 'any' type instead? +!!! error TS2322: Property 'charAt' is missing in type 'Object'. + var c: String = Object.create(1); + ~ +!!! error TS2322: Type 'Number' is not assignable to type 'String'. +!!! error TS2322: Property 'charAt' is missing in type 'Number'. + + var w: Error = new Object(); + ~ +!!! error TS2322: Type 'Object' is not assignable to type 'Error'. +!!! error TS2322: The 'Object' type is assignable to very few other types. Did you mean to use the 'any' type instead? +!!! error TS2322: Property 'name' is missing in type 'Object'. + \ No newline at end of file diff --git a/tests/baselines/reference/assigningFromObjectToAnythingElse.js b/tests/baselines/reference/assigningFromObjectToAnythingElse.js new file mode 100644 index 00000000000..61c4a6ede22 --- /dev/null +++ b/tests/baselines/reference/assigningFromObjectToAnythingElse.js @@ -0,0 +1,18 @@ +//// [assigningFromObjectToAnythingElse.ts] +var x: Object; +var y: RegExp; +y = x; + +var a: String = Object.create(""); +var c: String = Object.create(1); + +var w: Error = new Object(); + + +//// [assigningFromObjectToAnythingElse.js] +var x; +var y; +y = x; +var a = Object.create(""); +var c = Object.create(1); +var w = new Object(); diff --git a/tests/baselines/reference/controlFlowWithIncompleteTypes.js b/tests/baselines/reference/controlFlowWithIncompleteTypes.js new file mode 100644 index 00000000000..83940df6753 --- /dev/null +++ b/tests/baselines/reference/controlFlowWithIncompleteTypes.js @@ -0,0 +1,53 @@ +//// [controlFlowWithIncompleteTypes.ts] +// Repro from #11000 + +declare var cond: boolean; + +function foo1() { + let x: string | number | boolean = 0; + while (cond) { + if (typeof x === "string") { + x = x.slice(); + } + else { + x = "abc"; + } + } +} + +function foo2() { + let x: string | number | boolean = 0; + while (cond) { + if (typeof x === "number") { + x = "abc"; + } + else { + x = x.slice(); + } + } +} + +//// [controlFlowWithIncompleteTypes.js] +// Repro from #11000 +function foo1() { + var x = 0; + while (cond) { + if (typeof x === "string") { + x = x.slice(); + } + else { + x = "abc"; + } + } +} +function foo2() { + var x = 0; + while (cond) { + if (typeof x === "number") { + x = "abc"; + } + else { + x = x.slice(); + } + } +} diff --git a/tests/baselines/reference/controlFlowWithIncompleteTypes.symbols b/tests/baselines/reference/controlFlowWithIncompleteTypes.symbols new file mode 100644 index 00000000000..2ad709140cb --- /dev/null +++ b/tests/baselines/reference/controlFlowWithIncompleteTypes.symbols @@ -0,0 +1,55 @@ +=== tests/cases/compiler/controlFlowWithIncompleteTypes.ts === +// Repro from #11000 + +declare var cond: boolean; +>cond : Symbol(cond, Decl(controlFlowWithIncompleteTypes.ts, 2, 11)) + +function foo1() { +>foo1 : Symbol(foo1, Decl(controlFlowWithIncompleteTypes.ts, 2, 26)) + + let x: string | number | boolean = 0; +>x : Symbol(x, Decl(controlFlowWithIncompleteTypes.ts, 5, 7)) + + while (cond) { +>cond : Symbol(cond, Decl(controlFlowWithIncompleteTypes.ts, 2, 11)) + + if (typeof x === "string") { +>x : Symbol(x, Decl(controlFlowWithIncompleteTypes.ts, 5, 7)) + + x = x.slice(); +>x : Symbol(x, Decl(controlFlowWithIncompleteTypes.ts, 5, 7)) +>x.slice : Symbol(String.slice, Decl(lib.d.ts, --, --)) +>x : Symbol(x, Decl(controlFlowWithIncompleteTypes.ts, 5, 7)) +>slice : Symbol(String.slice, Decl(lib.d.ts, --, --)) + } + else { + x = "abc"; +>x : Symbol(x, Decl(controlFlowWithIncompleteTypes.ts, 5, 7)) + } + } +} + +function foo2() { +>foo2 : Symbol(foo2, Decl(controlFlowWithIncompleteTypes.ts, 14, 1)) + + let x: string | number | boolean = 0; +>x : Symbol(x, Decl(controlFlowWithIncompleteTypes.ts, 17, 7)) + + while (cond) { +>cond : Symbol(cond, Decl(controlFlowWithIncompleteTypes.ts, 2, 11)) + + if (typeof x === "number") { +>x : Symbol(x, Decl(controlFlowWithIncompleteTypes.ts, 17, 7)) + + x = "abc"; +>x : Symbol(x, Decl(controlFlowWithIncompleteTypes.ts, 17, 7)) + } + else { + x = x.slice(); +>x : Symbol(x, Decl(controlFlowWithIncompleteTypes.ts, 17, 7)) +>x.slice : Symbol(String.slice, Decl(lib.d.ts, --, --)) +>x : Symbol(x, Decl(controlFlowWithIncompleteTypes.ts, 17, 7)) +>slice : Symbol(String.slice, Decl(lib.d.ts, --, --)) + } + } +} diff --git a/tests/baselines/reference/controlFlowWithIncompleteTypes.types b/tests/baselines/reference/controlFlowWithIncompleteTypes.types new file mode 100644 index 00000000000..784f22a3966 --- /dev/null +++ b/tests/baselines/reference/controlFlowWithIncompleteTypes.types @@ -0,0 +1,71 @@ +=== tests/cases/compiler/controlFlowWithIncompleteTypes.ts === +// Repro from #11000 + +declare var cond: boolean; +>cond : boolean + +function foo1() { +>foo1 : () => void + + let x: string | number | boolean = 0; +>x : string | number | boolean +>0 : 0 + + while (cond) { +>cond : boolean + + if (typeof x === "string") { +>typeof x === "string" : boolean +>typeof x : string +>x : string | number +>"string" : "string" + + x = x.slice(); +>x = x.slice() : string +>x : string | number | boolean +>x.slice() : string +>x.slice : (start?: number, end?: number) => string +>x : string +>slice : (start?: number, end?: number) => string + } + else { + x = "abc"; +>x = "abc" : "abc" +>x : string | number | boolean +>"abc" : "abc" + } + } +} + +function foo2() { +>foo2 : () => void + + let x: string | number | boolean = 0; +>x : string | number | boolean +>0 : 0 + + while (cond) { +>cond : boolean + + if (typeof x === "number") { +>typeof x === "number" : boolean +>typeof x : string +>x : string | number +>"number" : "number" + + x = "abc"; +>x = "abc" : "abc" +>x : string | number | boolean +>"abc" : "abc" + } + else { + x = x.slice(); +>x = x.slice() : string +>x : string | number | boolean +>x.slice() : string +>x.slice : (start?: number, end?: number) => string +>x : string +>slice : (start?: number, end?: number) => string + } + } +} diff --git a/tests/cases/compiler/assigningFromObjectToAnythingElse.ts b/tests/cases/compiler/assigningFromObjectToAnythingElse.ts new file mode 100644 index 00000000000..ebf1a0a8763 --- /dev/null +++ b/tests/cases/compiler/assigningFromObjectToAnythingElse.ts @@ -0,0 +1,8 @@ +var x: Object; +var y: RegExp; +y = x; + +var a: String = Object.create(""); +var c: String = Object.create(1); + +var w: Error = new Object(); diff --git a/tests/cases/compiler/controlFlowWithIncompleteTypes.ts b/tests/cases/compiler/controlFlowWithIncompleteTypes.ts new file mode 100644 index 00000000000..a851e6652c8 --- /dev/null +++ b/tests/cases/compiler/controlFlowWithIncompleteTypes.ts @@ -0,0 +1,27 @@ +// Repro from #11000 + +declare var cond: boolean; + +function foo1() { + let x: string | number | boolean = 0; + while (cond) { + if (typeof x === "string") { + x = x.slice(); + } + else { + x = "abc"; + } + } +} + +function foo2() { + let x: string | number | boolean = 0; + while (cond) { + if (typeof x === "number") { + x = "abc"; + } + else { + x = x.slice(); + } + } +} \ No newline at end of file diff --git a/tests/cases/fourslash/navigationBarJsDocCommentWithNoTags.ts b/tests/cases/fourslash/navigationBarJsDocCommentWithNoTags.ts new file mode 100644 index 00000000000..8746f135e4d --- /dev/null +++ b/tests/cases/fourslash/navigationBarJsDocCommentWithNoTags.ts @@ -0,0 +1,18 @@ +/// + +/////** Test */ +////export const Test = {} + +verify.navigationBar([ + { + "text": "\"navigationBarJsDocCommentWithNoTags\"", + "kind": "module", + "childItems": [ + { + "text": "Test", + "kind": "const", + "kindModifiers": "export" + } + ] + } +]);