diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 1d6627987e151..b2bc42d891d86 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1287,12 +1287,6 @@ namespace ts { activeLabels!.pop(); } - function isDottedName(node: Expression): boolean { - return node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.ThisKeyword || - node.kind === SyntaxKind.PropertyAccessExpression && isDottedName((node).expression) || - node.kind === SyntaxKind.ParenthesizedExpression && isDottedName((node).expression); - } - function bindExpressionStatement(node: ExpressionStatement): void { bind(node.expression); // A top level call expression with a dotted function name and at least one argument diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7f3c1cfc43d16..3bc8d88f4fa2f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -17191,30 +17191,38 @@ namespace ts { getEffectiveTypeAnnotationNode(declaration as VariableDeclaration | ParameterDeclaration | PropertyDeclaration | PropertySignature)); } - function getExplicitTypeOfSymbol(symbol: Symbol) { - return symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.ValueModule) || - symbol.flags & (SymbolFlags.Variable | SymbolFlags.Property) && isDeclarationWithExplicitTypeAnnotation(symbol.valueDeclaration) ? - getTypeOfSymbol(symbol) : undefined; + function getExplicitTypeOfSymbol(symbol: Symbol, diagnostic?: Diagnostic) { + if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.ValueModule)) { + return getTypeOfSymbol(symbol); + } + if (symbol.flags & (SymbolFlags.Variable | SymbolFlags.Property)) { + if (isDeclarationWithExplicitTypeAnnotation(symbol.valueDeclaration)) { + return getTypeOfSymbol(symbol); + } + if (diagnostic && symbol.valueDeclaration) { + addRelatedInfo(diagnostic, createDiagnosticForNode(symbol.valueDeclaration, Diagnostics._0_is_declared_here, symbolToString(symbol))); + } + } } // We require the dotted function name in an assertion expression to be comprised of identifiers // that reference function, method, class or value module symbols; or variable, property or // parameter symbols with declarations that have explicit type annotations. Such references are // resolvable with no possibility of triggering circularities in control flow analysis. - function getTypeOfDottedName(node: Expression): Type | undefined { + function getTypeOfDottedName(node: Expression, diagnostic: Diagnostic | undefined): Type | undefined { if (!(node.flags & NodeFlags.InWithStatement)) { switch (node.kind) { case SyntaxKind.Identifier: - const symbol = getResolvedSymbol(node); - return getExplicitTypeOfSymbol(symbol.flags & SymbolFlags.Alias ? resolveAlias(symbol) : symbol); + const symbol = getExportSymbolOfValueSymbolIfExported(getResolvedSymbol(node)); + return getExplicitTypeOfSymbol(symbol.flags & SymbolFlags.Alias ? resolveAlias(symbol) : symbol, diagnostic); case SyntaxKind.ThisKeyword: return getExplicitThisType(node); case SyntaxKind.PropertyAccessExpression: - const type = getTypeOfDottedName((node).expression); + const type = getTypeOfDottedName((node).expression, diagnostic); const prop = type && getPropertyOfType(type, (node).name.escapedText); - return prop && getExplicitTypeOfSymbol(prop); + return prop && getExplicitTypeOfSymbol(prop, diagnostic); case SyntaxKind.ParenthesizedExpression: - return getTypeOfDottedName((node).expression); + return getTypeOfDottedName((node).expression, diagnostic); } } } @@ -17227,7 +17235,7 @@ namespace ts { // expressions are potential type predicate function calls. In order to avoid triggering // circularities in control flow analysis, we use getTypeOfDottedName when resolving the call // target expression of an assertion. - const funcType = node.parent.kind === SyntaxKind.ExpressionStatement ? getTypeOfDottedName(node.expression) : + const funcType = node.parent.kind === SyntaxKind.ExpressionStatement ? getTypeOfDottedName(node.expression, /*diagnostic*/ undefined) : node.expression.kind !== SyntaxKind.SuperKeyword ? checkNonNullExpression(node.expression) : undefined; const signatures = getSignaturesOfType(funcType && getApparentType(funcType) || unknownType, SignatureKind.Call); @@ -23416,6 +23424,16 @@ namespace ts { if (returnType.flags & TypeFlags.ESSymbolLike && isSymbolOrSymbolForCall(node)) { return getESSymbolLikeTypeForNode(walkUpParenthesizedExpressions(node.parent)); } + if (node.kind === SyntaxKind.CallExpression && node.parent.kind === SyntaxKind.ExpressionStatement && + returnType.flags & TypeFlags.Void && getTypePredicateOfSignature(signature)) { + if (!isDottedName(node.expression)) { + error(node.expression, Diagnostics.Assertions_require_the_call_target_to_be_an_identifier_or_qualified_name); + } + else if (!getEffectsSignature(node)) { + const diagnostic = error(node.expression, Diagnostics.Assertions_require_every_name_in_the_call_target_to_be_declared_with_an_explicit_type_annotation); + getTypeOfDottedName(node.expression, diagnostic); + } + } let jsAssignmentType: Type | undefined; if (isInJSFile(node)) { const decl = getDeclarationOfExpando(node); diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 87052c4e7cdb2..c0fd0632862fd 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2726,6 +2726,14 @@ "category": "Error", "code": 2774 }, + "Assertions require every name in the call target to be declared with an explicit type annotation.": { + "category": "Error", + "code": 2775 + }, + "Assertions require the call target to be an identifier or qualified name.": { + "category": "Error", + "code": 2776 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", "code": 4000 diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 6b48cb80625ee..9a6fd48c08af7 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -4062,6 +4062,12 @@ namespace ts { return node.kind === SyntaxKind.Identifier || isPropertyAccessEntityNameExpression(node); } + export function isDottedName(node: Expression): boolean { + return node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.ThisKeyword || + node.kind === SyntaxKind.PropertyAccessExpression && isDottedName((node).expression) || + node.kind === SyntaxKind.ParenthesizedExpression && isDottedName((node).expression); + } + export function isPropertyAccessEntityNameExpression(node: Node): node is PropertyAccessEntityNameExpression { return isPropertyAccessExpression(node) && isEntityNameExpression(node.expression); } diff --git a/tests/baselines/reference/assertionTypePredicates1.errors.txt b/tests/baselines/reference/assertionTypePredicates1.errors.txt index 91d2e869bd2e2..2fe95b995487f 100644 --- a/tests/baselines/reference/assertionTypePredicates1.errors.txt +++ b/tests/baselines/reference/assertionTypePredicates1.errors.txt @@ -5,9 +5,12 @@ tests/cases/conformance/controlFlow/assertionTypePredicates1.ts(121,15): error T tests/cases/conformance/controlFlow/assertionTypePredicates1.ts(122,15): error TS1228: A type predicate is only allowed in return type position for functions and methods. tests/cases/conformance/controlFlow/assertionTypePredicates1.ts(123,15): error TS1228: A type predicate is only allowed in return type position for functions and methods. tests/cases/conformance/controlFlow/assertionTypePredicates1.ts(124,15): error TS1228: A type predicate is only allowed in return type position for functions and methods. +tests/cases/conformance/controlFlow/assertionTypePredicates1.ts(129,5): error TS2775: Assertions require every name in the call target to be declared with an explicit type annotation. +tests/cases/conformance/controlFlow/assertionTypePredicates1.ts(131,5): error TS2776: Assertions require the call target to be an identifier or qualified name. +tests/cases/conformance/controlFlow/assertionTypePredicates1.ts(133,5): error TS2775: Assertions require every name in the call target to be declared with an explicit type annotation. -==== tests/cases/conformance/controlFlow/assertionTypePredicates1.ts (7 errors) ==== +==== tests/cases/conformance/controlFlow/assertionTypePredicates1.ts (10 errors) ==== declare function isString(value: unknown): value is string; declare function isArrayOfStrings(value: unknown): value is string[]; @@ -147,4 +150,23 @@ tests/cases/conformance/controlFlow/assertionTypePredicates1.ts(124,15): error T ~~~~~~~~~~~~~~~~~~~~~~ !!! error TS1228: A type predicate is only allowed in return type position for functions and methods. } + + function f20(x: unknown) { + const assert = (value: unknown): asserts value => {} + assert(typeof x === "string"); // Error + ~~~~~~ +!!! error TS2775: Assertions require every name in the call target to be declared with an explicit type annotation. +!!! related TS2728 tests/cases/conformance/controlFlow/assertionTypePredicates1.ts:128:11: 'assert' is declared here. + const a = [assert]; + a[0](typeof x === "string"); // Error + ~~~~ +!!! error TS2776: Assertions require the call target to be an identifier or qualified name. + const t1 = new Test(); + t1.assert(typeof x === "string"); // Error + ~~~~~~~~~ +!!! error TS2775: Assertions require every name in the call target to be declared with an explicit type annotation. +!!! related TS2728 tests/cases/conformance/controlFlow/assertionTypePredicates1.ts:132:11: 't1' is declared here. + const t2: Test = new Test(); + t2.assert(typeof x === "string"); + } \ No newline at end of file diff --git a/tests/baselines/reference/assertionTypePredicates1.js b/tests/baselines/reference/assertionTypePredicates1.js index ad21d116b73ab..145bb98bce980 100644 --- a/tests/baselines/reference/assertionTypePredicates1.js +++ b/tests/baselines/reference/assertionTypePredicates1.js @@ -124,6 +124,17 @@ declare class Wat { get p2(): asserts this is string; set p2(x: asserts this is string); } + +function f20(x: unknown) { + const assert = (value: unknown): asserts value => {} + assert(typeof x === "string"); // Error + const a = [assert]; + a[0](typeof x === "string"); // Error + const t1 = new Test(); + t1.assert(typeof x === "string"); // Error + const t2: Test = new Test(); + t2.assert(typeof x === "string"); +} //// [assertionTypePredicates1.js] @@ -250,6 +261,16 @@ var Test2 = /** @class */ (function (_super) { } return Test2; }(Test)); +function f20(x) { + var assert = function (value) { }; + assert(typeof x === "string"); // Error + var a = [assert]; + a[0](typeof x === "string"); // Error + var t1 = new Test(); + t1.assert(typeof x === "string"); // Error + var t2 = new Test(); + t2.assert(typeof x === "string"); +} //// [assertionTypePredicates1.d.ts] @@ -287,3 +308,4 @@ declare class Wat { get p2(): asserts this is string; set p2(x: asserts this is string); } +declare function f20(x: unknown): void; diff --git a/tests/baselines/reference/assertionTypePredicates1.symbols b/tests/baselines/reference/assertionTypePredicates1.symbols index c68a1926aff49..af43ab29864e1 100644 --- a/tests/baselines/reference/assertionTypePredicates1.symbols +++ b/tests/baselines/reference/assertionTypePredicates1.symbols @@ -357,3 +357,46 @@ declare class Wat { >x : Symbol(x, Decl(assertionTypePredicates1.ts, 123, 11)) } +function f20(x: unknown) { +>f20 : Symbol(f20, Decl(assertionTypePredicates1.ts, 124, 1)) +>x : Symbol(x, Decl(assertionTypePredicates1.ts, 126, 13)) + + const assert = (value: unknown): asserts value => {} +>assert : Symbol(assert, Decl(assertionTypePredicates1.ts, 127, 9)) +>value : Symbol(value, Decl(assertionTypePredicates1.ts, 127, 20)) +>value : Symbol(value, Decl(assertionTypePredicates1.ts, 127, 20)) + + assert(typeof x === "string"); // Error +>assert : Symbol(assert, Decl(assertionTypePredicates1.ts, 127, 9)) +>x : Symbol(x, Decl(assertionTypePredicates1.ts, 126, 13)) + + const a = [assert]; +>a : Symbol(a, Decl(assertionTypePredicates1.ts, 129, 9)) +>assert : Symbol(assert, Decl(assertionTypePredicates1.ts, 127, 9)) + + a[0](typeof x === "string"); // Error +>a : Symbol(a, Decl(assertionTypePredicates1.ts, 129, 9)) +>x : Symbol(x, Decl(assertionTypePredicates1.ts, 126, 13)) + + const t1 = new Test(); +>t1 : Symbol(t1, Decl(assertionTypePredicates1.ts, 131, 9)) +>Test : Symbol(Test, Decl(assertionTypePredicates1.ts, 76, 1)) + + t1.assert(typeof x === "string"); // Error +>t1.assert : Symbol(Test.assert, Decl(assertionTypePredicates1.ts, 78, 12)) +>t1 : Symbol(t1, Decl(assertionTypePredicates1.ts, 131, 9)) +>assert : Symbol(Test.assert, Decl(assertionTypePredicates1.ts, 78, 12)) +>x : Symbol(x, Decl(assertionTypePredicates1.ts, 126, 13)) + + const t2: Test = new Test(); +>t2 : Symbol(t2, Decl(assertionTypePredicates1.ts, 133, 9)) +>Test : Symbol(Test, Decl(assertionTypePredicates1.ts, 76, 1)) +>Test : Symbol(Test, Decl(assertionTypePredicates1.ts, 76, 1)) + + t2.assert(typeof x === "string"); +>t2.assert : Symbol(Test.assert, Decl(assertionTypePredicates1.ts, 78, 12)) +>t2 : Symbol(t2, Decl(assertionTypePredicates1.ts, 133, 9)) +>assert : Symbol(Test.assert, Decl(assertionTypePredicates1.ts, 78, 12)) +>x : Symbol(x, Decl(assertionTypePredicates1.ts, 126, 13)) +} + diff --git a/tests/baselines/reference/assertionTypePredicates1.types b/tests/baselines/reference/assertionTypePredicates1.types index f72ec641013aa..470478b3fe48c 100644 --- a/tests/baselines/reference/assertionTypePredicates1.types +++ b/tests/baselines/reference/assertionTypePredicates1.types @@ -436,3 +436,66 @@ declare class Wat { >x : void } +function f20(x: unknown) { +>f20 : (x: unknown) => void +>x : unknown + + const assert = (value: unknown): asserts value => {} +>assert : (value: unknown) => asserts value +>(value: unknown): asserts value => {} : (value: unknown) => asserts value +>value : unknown + + assert(typeof x === "string"); // Error +>assert(typeof x === "string") : void +>assert : (value: unknown) => asserts value +>typeof x === "string" : boolean +>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>x : unknown +>"string" : "string" + + const a = [assert]; +>a : ((value: unknown) => asserts value)[] +>[assert] : ((value: unknown) => asserts value)[] +>assert : (value: unknown) => asserts value + + a[0](typeof x === "string"); // Error +>a[0](typeof x === "string") : void +>a[0] : (value: unknown) => asserts value +>a : ((value: unknown) => asserts value)[] +>0 : 0 +>typeof x === "string" : boolean +>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>x : unknown +>"string" : "string" + + const t1 = new Test(); +>t1 : Test +>new Test() : Test +>Test : typeof Test + + t1.assert(typeof x === "string"); // Error +>t1.assert(typeof x === "string") : void +>t1.assert : (value: unknown) => asserts value +>t1 : Test +>assert : (value: unknown) => asserts value +>typeof x === "string" : boolean +>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>x : unknown +>"string" : "string" + + const t2: Test = new Test(); +>t2 : Test +>new Test() : Test +>Test : typeof Test + + t2.assert(typeof x === "string"); +>t2.assert(typeof x === "string") : void +>t2.assert : (value: unknown) => asserts value +>t2 : Test +>assert : (value: unknown) => asserts value +>typeof x === "string" : boolean +>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>x : unknown +>"string" : "string" +} + diff --git a/tests/baselines/reference/neverReturningFunctions1.errors.txt b/tests/baselines/reference/neverReturningFunctions1.errors.txt index 5eb6659427c46..73713465e7d29 100644 --- a/tests/baselines/reference/neverReturningFunctions1.errors.txt +++ b/tests/baselines/reference/neverReturningFunctions1.errors.txt @@ -225,6 +225,14 @@ tests/cases/conformance/controlFlow/neverReturningFunctions1.ts(153,5): error TS !!! error TS7027: Unreachable code detected. } + function f43() { + const fail = (): never => { throw new Error(); }; + const f = [fail]; + fail(); // No effect (missing type annotation) + f[0](); // No effect (not a dotted name) + f; + } + // Repro from #33582 export interface Component { diff --git a/tests/baselines/reference/neverReturningFunctions1.js b/tests/baselines/reference/neverReturningFunctions1.js index a99cc51e06dad..e6f13468cc60e 100644 --- a/tests/baselines/reference/neverReturningFunctions1.js +++ b/tests/baselines/reference/neverReturningFunctions1.js @@ -154,6 +154,14 @@ function f42(x: number) { x; // Unreachable } +function f43() { + const fail = (): never => { throw new Error(); }; + const f = [fail]; + fail(); // No effect (missing type annotation) + f[0](); // No effect (not a dotted name) + f; +} + // Repro from #33582 export interface Component { @@ -375,6 +383,13 @@ function f42(x) { } x; // Unreachable } +function f43() { + var fail = function () { throw new Error(); }; + var f = [fail]; + fail(); // No effect (missing type annotation) + f[0](); // No effect (not a dotted name) + f; +} var Component = registerComponent('test-component', { schema: { myProperty: { diff --git a/tests/baselines/reference/neverReturningFunctions1.symbols b/tests/baselines/reference/neverReturningFunctions1.symbols index 2ec4c5f93d38a..b73830503bf9c 100644 --- a/tests/baselines/reference/neverReturningFunctions1.symbols +++ b/tests/baselines/reference/neverReturningFunctions1.symbols @@ -385,196 +385,217 @@ function f42(x: number) { >x : Symbol(x, Decl(neverReturningFunctions1.ts, 143, 13)) } +function f43() { +>f43 : Symbol(f43, Decl(neverReturningFunctions1.ts, 153, 1)) + + const fail = (): never => { throw new Error(); }; +>fail : Symbol(fail, Decl(neverReturningFunctions1.ts, 156, 9)) +>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + + const f = [fail]; +>f : Symbol(f, Decl(neverReturningFunctions1.ts, 157, 9)) +>fail : Symbol(fail, Decl(neverReturningFunctions1.ts, 156, 9)) + + fail(); // No effect (missing type annotation) +>fail : Symbol(fail, Decl(neverReturningFunctions1.ts, 156, 9)) + + f[0](); // No effect (not a dotted name) +>f : Symbol(f, Decl(neverReturningFunctions1.ts, 157, 9)) + + f; +>f : Symbol(f, Decl(neverReturningFunctions1.ts, 157, 9)) +} + // Repro from #33582 export interface Component { ->Component : Symbol(Component, Decl(neverReturningFunctions1.ts, 153, 1)) ->T : Symbol(T, Decl(neverReturningFunctions1.ts, 157, 27)) +>Component : Symbol(Component, Decl(neverReturningFunctions1.ts, 161, 1)) +>T : Symbol(T, Decl(neverReturningFunctions1.ts, 165, 27)) attrName?: string; ->attrName : Symbol(Component.attrName, Decl(neverReturningFunctions1.ts, 157, 52)) +>attrName : Symbol(Component.attrName, Decl(neverReturningFunctions1.ts, 165, 52)) data: T; ->data : Symbol(Component.data, Decl(neverReturningFunctions1.ts, 158, 19)) ->T : Symbol(T, Decl(neverReturningFunctions1.ts, 157, 27)) +>data : Symbol(Component.data, Decl(neverReturningFunctions1.ts, 166, 19)) +>T : Symbol(T, Decl(neverReturningFunctions1.ts, 165, 27)) dependencies?: string[]; ->dependencies : Symbol(Component.dependencies, Decl(neverReturningFunctions1.ts, 159, 9)) +>dependencies : Symbol(Component.dependencies, Decl(neverReturningFunctions1.ts, 167, 9)) el: any; ->el : Symbol(Component.el, Decl(neverReturningFunctions1.ts, 160, 25)) +>el : Symbol(Component.el, Decl(neverReturningFunctions1.ts, 168, 25)) id: string; ->id : Symbol(Component.id, Decl(neverReturningFunctions1.ts, 161, 9)) +>id : Symbol(Component.id, Decl(neverReturningFunctions1.ts, 169, 9)) multiple?: boolean; ->multiple : Symbol(Component.multiple, Decl(neverReturningFunctions1.ts, 162, 12)) +>multiple : Symbol(Component.multiple, Decl(neverReturningFunctions1.ts, 170, 12)) name: string; ->name : Symbol(Component.name, Decl(neverReturningFunctions1.ts, 163, 20)) +>name : Symbol(Component.name, Decl(neverReturningFunctions1.ts, 171, 20)) schema: unknown; ->schema : Symbol(Component.schema, Decl(neverReturningFunctions1.ts, 164, 14)) +>schema : Symbol(Component.schema, Decl(neverReturningFunctions1.ts, 172, 14)) system: any; ->system : Symbol(Component.system, Decl(neverReturningFunctions1.ts, 165, 17)) +>system : Symbol(Component.system, Decl(neverReturningFunctions1.ts, 173, 17)) init(data?: T): void; ->init : Symbol(Component.init, Decl(neverReturningFunctions1.ts, 166, 13)) ->data : Symbol(data, Decl(neverReturningFunctions1.ts, 168, 6)) ->T : Symbol(T, Decl(neverReturningFunctions1.ts, 157, 27)) +>init : Symbol(Component.init, Decl(neverReturningFunctions1.ts, 174, 13)) +>data : Symbol(data, Decl(neverReturningFunctions1.ts, 176, 6)) +>T : Symbol(T, Decl(neverReturningFunctions1.ts, 165, 27)) pause(): void; ->pause : Symbol(Component.pause, Decl(neverReturningFunctions1.ts, 168, 22)) +>pause : Symbol(Component.pause, Decl(neverReturningFunctions1.ts, 176, 22)) play(): void; ->play : Symbol(Component.play, Decl(neverReturningFunctions1.ts, 169, 15)) +>play : Symbol(Component.play, Decl(neverReturningFunctions1.ts, 177, 15)) remove(): void; ->remove : Symbol(Component.remove, Decl(neverReturningFunctions1.ts, 170, 14)) +>remove : Symbol(Component.remove, Decl(neverReturningFunctions1.ts, 178, 14)) tick?(time: number, timeDelta: number): void; ->tick : Symbol(Component.tick, Decl(neverReturningFunctions1.ts, 171, 16)) ->time : Symbol(time, Decl(neverReturningFunctions1.ts, 172, 7)) ->timeDelta : Symbol(timeDelta, Decl(neverReturningFunctions1.ts, 172, 20)) +>tick : Symbol(Component.tick, Decl(neverReturningFunctions1.ts, 179, 16)) +>time : Symbol(time, Decl(neverReturningFunctions1.ts, 180, 7)) +>timeDelta : Symbol(timeDelta, Decl(neverReturningFunctions1.ts, 180, 20)) update(oldData: T): void; ->update : Symbol(Component.update, Decl(neverReturningFunctions1.ts, 172, 46)) ->oldData : Symbol(oldData, Decl(neverReturningFunctions1.ts, 173, 8)) ->T : Symbol(T, Decl(neverReturningFunctions1.ts, 157, 27)) +>update : Symbol(Component.update, Decl(neverReturningFunctions1.ts, 180, 46)) +>oldData : Symbol(oldData, Decl(neverReturningFunctions1.ts, 181, 8)) +>T : Symbol(T, Decl(neverReturningFunctions1.ts, 165, 27)) updateSchema?(): void; ->updateSchema : Symbol(Component.updateSchema, Decl(neverReturningFunctions1.ts, 173, 26)) +>updateSchema : Symbol(Component.updateSchema, Decl(neverReturningFunctions1.ts, 181, 26)) extendSchema(update: unknown): void; ->extendSchema : Symbol(Component.extendSchema, Decl(neverReturningFunctions1.ts, 174, 23)) ->update : Symbol(update, Decl(neverReturningFunctions1.ts, 176, 14)) +>extendSchema : Symbol(Component.extendSchema, Decl(neverReturningFunctions1.ts, 182, 23)) +>update : Symbol(update, Decl(neverReturningFunctions1.ts, 184, 14)) flushToDOM(): void; ->flushToDOM : Symbol(Component.flushToDOM, Decl(neverReturningFunctions1.ts, 176, 37)) +>flushToDOM : Symbol(Component.flushToDOM, Decl(neverReturningFunctions1.ts, 184, 37)) } export interface ComponentConstructor { ->ComponentConstructor : Symbol(ComponentConstructor, Decl(neverReturningFunctions1.ts, 178, 1)) ->T : Symbol(T, Decl(neverReturningFunctions1.ts, 180, 38)) +>ComponentConstructor : Symbol(ComponentConstructor, Decl(neverReturningFunctions1.ts, 186, 1)) +>T : Symbol(T, Decl(neverReturningFunctions1.ts, 188, 38)) new (el: unknown, attrValue: string, id: string): T & Component; ->el : Symbol(el, Decl(neverReturningFunctions1.ts, 181, 6)) ->attrValue : Symbol(attrValue, Decl(neverReturningFunctions1.ts, 181, 18)) ->id : Symbol(id, Decl(neverReturningFunctions1.ts, 181, 37)) ->T : Symbol(T, Decl(neverReturningFunctions1.ts, 180, 38)) ->Component : Symbol(Component, Decl(neverReturningFunctions1.ts, 153, 1)) +>el : Symbol(el, Decl(neverReturningFunctions1.ts, 189, 6)) +>attrValue : Symbol(attrValue, Decl(neverReturningFunctions1.ts, 189, 18)) +>id : Symbol(id, Decl(neverReturningFunctions1.ts, 189, 37)) +>T : Symbol(T, Decl(neverReturningFunctions1.ts, 188, 38)) +>Component : Symbol(Component, Decl(neverReturningFunctions1.ts, 161, 1)) prototype: T & { ->prototype : Symbol(ComponentConstructor.prototype, Decl(neverReturningFunctions1.ts, 181, 65)) ->T : Symbol(T, Decl(neverReturningFunctions1.ts, 180, 38)) +>prototype : Symbol(ComponentConstructor.prototype, Decl(neverReturningFunctions1.ts, 189, 65)) +>T : Symbol(T, Decl(neverReturningFunctions1.ts, 188, 38)) name: string; ->name : Symbol(name, Decl(neverReturningFunctions1.ts, 182, 17)) +>name : Symbol(name, Decl(neverReturningFunctions1.ts, 190, 17)) system: unknown; ->system : Symbol(system, Decl(neverReturningFunctions1.ts, 183, 15)) +>system : Symbol(system, Decl(neverReturningFunctions1.ts, 191, 15)) play(): void; ->play : Symbol(play, Decl(neverReturningFunctions1.ts, 184, 18)) +>play : Symbol(play, Decl(neverReturningFunctions1.ts, 192, 18)) pause(): void; ->pause : Symbol(pause, Decl(neverReturningFunctions1.ts, 185, 15)) +>pause : Symbol(pause, Decl(neverReturningFunctions1.ts, 193, 15)) }; } declare function registerComponent( ->registerComponent : Symbol(registerComponent, Decl(neverReturningFunctions1.ts, 188, 1)) ->T : Symbol(T, Decl(neverReturningFunctions1.ts, 190, 35)) +>registerComponent : Symbol(registerComponent, Decl(neverReturningFunctions1.ts, 196, 1)) +>T : Symbol(T, Decl(neverReturningFunctions1.ts, 198, 35)) name: string, ->name : Symbol(name, Decl(neverReturningFunctions1.ts, 190, 53)) +>name : Symbol(name, Decl(neverReturningFunctions1.ts, 198, 53)) component: ComponentDefinition ->component : Symbol(component, Decl(neverReturningFunctions1.ts, 191, 17)) ->ComponentDefinition : Symbol(ComponentDefinition, Decl(neverReturningFunctions1.ts, 193, 27)) ->T : Symbol(T, Decl(neverReturningFunctions1.ts, 190, 35)) +>component : Symbol(component, Decl(neverReturningFunctions1.ts, 199, 17)) +>ComponentDefinition : Symbol(ComponentDefinition, Decl(neverReturningFunctions1.ts, 201, 27)) +>T : Symbol(T, Decl(neverReturningFunctions1.ts, 198, 35)) ): ComponentConstructor; ->ComponentConstructor : Symbol(ComponentConstructor, Decl(neverReturningFunctions1.ts, 178, 1)) ->T : Symbol(T, Decl(neverReturningFunctions1.ts, 190, 35)) +>ComponentConstructor : Symbol(ComponentConstructor, Decl(neverReturningFunctions1.ts, 186, 1)) +>T : Symbol(T, Decl(neverReturningFunctions1.ts, 198, 35)) export type ComponentDefinition = T & Partial & ThisType; ->ComponentDefinition : Symbol(ComponentDefinition, Decl(neverReturningFunctions1.ts, 193, 27)) ->T : Symbol(T, Decl(neverReturningFunctions1.ts, 195, 32)) ->T : Symbol(T, Decl(neverReturningFunctions1.ts, 195, 32)) +>ComponentDefinition : Symbol(ComponentDefinition, Decl(neverReturningFunctions1.ts, 201, 27)) +>T : Symbol(T, Decl(neverReturningFunctions1.ts, 203, 32)) +>T : Symbol(T, Decl(neverReturningFunctions1.ts, 203, 32)) >Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) ->Component : Symbol(Component, Decl(neverReturningFunctions1.ts, 153, 1)) +>Component : Symbol(Component, Decl(neverReturningFunctions1.ts, 161, 1)) >ThisType : Symbol(ThisType, Decl(lib.es5.d.ts, --, --)) ->T : Symbol(T, Decl(neverReturningFunctions1.ts, 195, 32)) ->Component : Symbol(Component, Decl(neverReturningFunctions1.ts, 153, 1)) +>T : Symbol(T, Decl(neverReturningFunctions1.ts, 203, 32)) +>Component : Symbol(Component, Decl(neverReturningFunctions1.ts, 161, 1)) const Component = registerComponent('test-component', { ->Component : Symbol(Component, Decl(neverReturningFunctions1.ts, 153, 1), Decl(neverReturningFunctions1.ts, 197, 5)) ->registerComponent : Symbol(registerComponent, Decl(neverReturningFunctions1.ts, 188, 1)) +>Component : Symbol(Component, Decl(neverReturningFunctions1.ts, 161, 1), Decl(neverReturningFunctions1.ts, 205, 5)) +>registerComponent : Symbol(registerComponent, Decl(neverReturningFunctions1.ts, 196, 1)) schema: { ->schema : Symbol(schema, Decl(neverReturningFunctions1.ts, 197, 55)) +>schema : Symbol(schema, Decl(neverReturningFunctions1.ts, 205, 55)) myProperty: { ->myProperty : Symbol(myProperty, Decl(neverReturningFunctions1.ts, 198, 10)) +>myProperty : Symbol(myProperty, Decl(neverReturningFunctions1.ts, 206, 10)) default: [], ->default : Symbol(default, Decl(neverReturningFunctions1.ts, 199, 15)) +>default : Symbol(default, Decl(neverReturningFunctions1.ts, 207, 15)) parse() { ->parse : Symbol(parse, Decl(neverReturningFunctions1.ts, 200, 15)) +>parse : Symbol(parse, Decl(neverReturningFunctions1.ts, 208, 15)) return [true]; } }, string: { type: 'string' }, ->string : Symbol(string, Decl(neverReturningFunctions1.ts, 204, 4)) ->type : Symbol(type, Decl(neverReturningFunctions1.ts, 205, 11)) +>string : Symbol(string, Decl(neverReturningFunctions1.ts, 212, 4)) +>type : Symbol(type, Decl(neverReturningFunctions1.ts, 213, 11)) num: 0 ->num : Symbol(num, Decl(neverReturningFunctions1.ts, 205, 29)) +>num : Symbol(num, Decl(neverReturningFunctions1.ts, 213, 29)) }, init() { ->init : Symbol(init, Decl(neverReturningFunctions1.ts, 207, 3)) +>init : Symbol(init, Decl(neverReturningFunctions1.ts, 215, 3)) this.data.num = 0; ->this.data : Symbol(Component.data, Decl(neverReturningFunctions1.ts, 158, 19)) ->data : Symbol(Component.data, Decl(neverReturningFunctions1.ts, 158, 19)) +>this.data : Symbol(Component.data, Decl(neverReturningFunctions1.ts, 166, 19)) +>data : Symbol(Component.data, Decl(neverReturningFunctions1.ts, 166, 19)) this.el.setAttribute('custom-attribute', 'custom-value'); ->this.el : Symbol(Component.el, Decl(neverReturningFunctions1.ts, 160, 25)) ->el : Symbol(Component.el, Decl(neverReturningFunctions1.ts, 160, 25)) +>this.el : Symbol(Component.el, Decl(neverReturningFunctions1.ts, 168, 25)) +>el : Symbol(Component.el, Decl(neverReturningFunctions1.ts, 168, 25)) }, update() {}, ->update : Symbol(update, Decl(neverReturningFunctions1.ts, 211, 3)) +>update : Symbol(update, Decl(neverReturningFunctions1.ts, 219, 3)) tick() {}, ->tick : Symbol(tick, Decl(neverReturningFunctions1.ts, 212, 13)) +>tick : Symbol(tick, Decl(neverReturningFunctions1.ts, 220, 13)) remove() {}, ->remove : Symbol(remove, Decl(neverReturningFunctions1.ts, 213, 11)) +>remove : Symbol(remove, Decl(neverReturningFunctions1.ts, 221, 11)) pause() {}, ->pause : Symbol(pause, Decl(neverReturningFunctions1.ts, 214, 13)) +>pause : Symbol(pause, Decl(neverReturningFunctions1.ts, 222, 13)) play() {}, ->play : Symbol(play, Decl(neverReturningFunctions1.ts, 215, 12)) +>play : Symbol(play, Decl(neverReturningFunctions1.ts, 223, 12)) multiply(f: number) { ->multiply : Symbol(multiply, Decl(neverReturningFunctions1.ts, 216, 11)) ->f : Symbol(f, Decl(neverReturningFunctions1.ts, 218, 10)) +>multiply : Symbol(multiply, Decl(neverReturningFunctions1.ts, 224, 11)) +>f : Symbol(f, Decl(neverReturningFunctions1.ts, 226, 10)) // Reference to system because both were registered with the same name. return f * this.data.num * this.system!.data.counter; ->f : Symbol(f, Decl(neverReturningFunctions1.ts, 218, 10)) ->this.data : Symbol(Component.data, Decl(neverReturningFunctions1.ts, 158, 19)) ->data : Symbol(Component.data, Decl(neverReturningFunctions1.ts, 158, 19)) ->this.system : Symbol(Component.system, Decl(neverReturningFunctions1.ts, 165, 17)) ->system : Symbol(Component.system, Decl(neverReturningFunctions1.ts, 165, 17)) +>f : Symbol(f, Decl(neverReturningFunctions1.ts, 226, 10)) +>this.data : Symbol(Component.data, Decl(neverReturningFunctions1.ts, 166, 19)) +>data : Symbol(Component.data, Decl(neverReturningFunctions1.ts, 166, 19)) +>this.system : Symbol(Component.system, Decl(neverReturningFunctions1.ts, 173, 17)) +>system : Symbol(Component.system, Decl(neverReturningFunctions1.ts, 173, 17)) } }); diff --git a/tests/baselines/reference/neverReturningFunctions1.types b/tests/baselines/reference/neverReturningFunctions1.types index ed49d1841b878..d92d2472b4d05 100644 --- a/tests/baselines/reference/neverReturningFunctions1.types +++ b/tests/baselines/reference/neverReturningFunctions1.types @@ -437,6 +437,34 @@ function f42(x: number) { >x : number } +function f43() { +>f43 : () => void + + const fail = (): never => { throw new Error(); }; +>fail : () => never +>(): never => { throw new Error(); } : () => never +>new Error() : Error +>Error : ErrorConstructor + + const f = [fail]; +>f : (() => never)[] +>[fail] : (() => never)[] +>fail : () => never + + fail(); // No effect (missing type annotation) +>fail() : never +>fail : () => never + + f[0](); // No effect (not a dotted name) +>f[0]() : never +>f[0] : () => never +>f : (() => never)[] +>0 : 0 + + f; +>f : (() => never)[] +} + // Repro from #33582 export interface Component { diff --git a/tests/cases/conformance/controlFlow/assertionTypePredicates1.ts b/tests/cases/conformance/controlFlow/assertionTypePredicates1.ts index b20cd42414b53..4cc73d5c91758 100644 --- a/tests/cases/conformance/controlFlow/assertionTypePredicates1.ts +++ b/tests/cases/conformance/controlFlow/assertionTypePredicates1.ts @@ -126,3 +126,14 @@ declare class Wat { get p2(): asserts this is string; set p2(x: asserts this is string); } + +function f20(x: unknown) { + const assert = (value: unknown): asserts value => {} + assert(typeof x === "string"); // Error + const a = [assert]; + a[0](typeof x === "string"); // Error + const t1 = new Test(); + t1.assert(typeof x === "string"); // Error + const t2: Test = new Test(); + t2.assert(typeof x === "string"); +} diff --git a/tests/cases/conformance/controlFlow/neverReturningFunctions1.ts b/tests/cases/conformance/controlFlow/neverReturningFunctions1.ts index 72dd0a13b5ae0..3a4e2899ca26f 100644 --- a/tests/cases/conformance/controlFlow/neverReturningFunctions1.ts +++ b/tests/cases/conformance/controlFlow/neverReturningFunctions1.ts @@ -157,6 +157,14 @@ function f42(x: number) { x; // Unreachable } +function f43() { + const fail = (): never => { throw new Error(); }; + const f = [fail]; + fail(); // No effect (missing type annotation) + f[0](); // No effect (not a dotted name) + f; +} + // Repro from #33582 export interface Component {