Now that TypeScript does [control flow based type analysis](https://github.com/Microsoft/TypeScript/pull/8010), and there is a [`never` type](https://github.com/Microsoft/TypeScript/pull/8652) in the works, is it possible to consider providing better type checking around `assert(...)` function calls that assert that a variable has a certain type at runtime? **TL;DR: some `assert` functions are really just type guards that signal via `return`/`throw` rather than `true`/`false`.** Example: ``` ts assert(typeof s === "string"); // throws if s is not a string s.length; // s is narrowed to string here... ``` ### Problem Asserts are common in contract-based programming, but I've also been coming across this scenario regularly whilst traversing JavaScript ASTs based on the [Parser API](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Parser_API) (I'm using babel to produce/traverse ASTs). For example, consider the `MemberExpression`:  Note we can assume `property` is an `Identifier` if `computed===false`. This is what I'd like to write: ``` ts function foo(expr: MemberExprssion) { if (expr.computed) { // handle computed case } else { // since computed===false, we know property must be an Identifier assert(isIdentifier(expr.property)); let name = expr.property.name; // ERROR: name doesn't exist on Identifier|Expression } } ``` Unfortunately that doesn't compile, because `expr.property` does not get narrowed after the `assert(...)` call. To get the full benefit of control flow analysis currently, you have to expand the assert call inline: ``` ts ... else { if (!isIdentifier(expr.property)) { throw new AssertionError(`Expected property to be an Identifier`); } let name = expr.property.name; // OK } ... ``` While preparing the typings for [`babel-core`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/babel-core/babel-core.d.ts), [`babel-types`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/babel-types/babel-types.d.ts) and friends, I noticed that using asserts this way is the norm. `babel-types` actually provides an `assertXXX` method for every `isXXX` method. These `assertXXX` functions are really just type guards that signal via `return`/`throw` rather than `true`/`false`. ### Possible Solutions? Not sure if it's feasible at all! But the new work on `never` in #8652 suggests a few possibilities. #### Specific assertions: assertIsT(...) ``` ts // normal type guard function isIdentifier(n: Node): n is Identifier { return n.type === 'Identifier'; } // PROPOSED SYNTAX: assert type guard function assertIdentifier(n: Node): n is Identifier | never { if (n.type !== 'Identifier') { throw new AssertionError(`Expected an Identifier`); } } ``` The compiler would reason that if this assert call returns at all, then it can safely narrow the variable type in following code. #### General assertions used with type guards: assert(isT(...)) The more general `assert(cond: boolean)` function would need a different approach and might not be feasible, but here's an idea: ``` ts // General case declare function assert(cond: boolean): void; // PROPOSED SYNTAX: Special overload for expressions of the form assert(isT(x)) declare function assert<T>(guard: guard is T): void | never; ``` For that second `assert` overload to work, the compiler on seeing `assert(isT(x))` would have to somehow forward the `x is T` narrowing from the `isT(x)` expression to the `assert(...)` expression at compile-time. Would be great if it also detected/handled things like `assert(typeof x == 'string')`. Not sure if any of this would meet the cost/benefit bar, but it's just an idea.