-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Description
Our team is just checking out AVA, and so far so good. Thanks for making it!
Background
TypeScript 3.7 introduces assertion functions. This is a control-flow-analysis (CFA) feature targeted at functions like several of those that AVA provides.
Example
Suppose that you have a Result
union type that discriminates on whether its success
property is true
or false
.
type Result =
| { success: true, good_stuff: any }
| { success: false, bad_stuff: any }
Currently, if you say
const result = some_function_returning_result()
t.assert(result.success)
// result is not narrowed, so
// Error: Property 'good_stuff' does not exist on type 'Result'
const { good_stuff } = result;
TS doesn't know that result
can now be narrowed to half of the union, even though that's clearly the intent (and effect) of the assertion.
Instead, you have to write
const result = some_function_returning_result()
t.assert(result.success)
if (result.success) {
// now result is narrowed
const { good_stuff } = result;
}
With assert signatures (which essentially implies the if
block as written above), TS will know that after the assert
call, result
has good_stuff
and not bad_stuff
.
Solution
For assert
this can be accomplished through a simple change to the AssertAssertion
interface in index.d.ts
:
- (actual: any, message?: string): void;
+ (actual: any, message?: string): asserts actual;
Stronger signatures are possible for the other functions. I first wanted to see whether this was a non-starter for some reason before digging into the others.
Note that you can't achieve the same thing with module augmentation. The following attempt
declare module "ava" {
interface AssertAssertion {
(actual: any, message?: string): asserts actual;
}
}
Results in error TS 2775
Assertions require every name in the call target to be declared with an explicit type annotation
I believe this is because the type extension does not remove the existing overload, which returns void
rather than an assertion. See microsoft/TypeScript#33622
Drawbacks
I always stay on the latest TypeScript version, and I haven't researched how this change would affect users who are pegged to earlier versions. This is the only downside I can think of.