-
Notifications
You must be signed in to change notification settings - Fork 13k
Description
TypeScript Version: 2.5.3
function invariant(condition: any, message: string): void {
if (!condition) {
throw new Error(message);
}
}
function double(a: number | string) {
invariant(typeof a === 'number', 'Sorry, strings not supported yet');
return a * 2;
}
Expected behavior:
invariant
should establish a type guard for the code following the invariant statement.
Actual behavior:
TypeScript errors with error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
This is because a
still resolves to type string | number
.
Suggestion:
invariant
ensures that its first argument condition
is truthy, and throws otherwise, i.e. when the code following the invariant statement is reached it is safe to make all the same assumptions as if that code were wrapped in if (condition) { … }
, or equivalently, the invariant were replaced with its literal implementation.
Although the latter works as a regular type guard (if (typeof a !== 'number') { throw … }
), it makes the code unnecessarily verbose. I think there should be a way of declaring that a given function guarantees that some guard is active, and never returns otherwise, i.e. something like this (pseudo code):
declare function invariant(condition: any, message: string): void if testValue;