-
Notifications
You must be signed in to change notification settings - Fork 13k
Description
Suggestion
π Search Terms
- type guard never
- satisfies
β Viability Checklist
My suggestion meets these guidelines:
- This wouldn't be a breaking change in existing TypeScript/JavaScript code
- This wouldn't change the runtime behavior of existing JavaScript code
- This could be implemented without emitting different JS based on the types of the expressions
- This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
- This feature would agree with the rest of TypeScript's Design Goals.
β Suggestion
Currently, the "User-Defined Type Guards" feature can be used to define a function where the boolean return value indicated whether or not an argument has a certain type.
This feature request is for a similar feature where a function returns true
or throws an error to indicate whether or not an argument is will return if an argument is of a type or throw an error if it is not of that type. The use case is simplifying unit tests written in TypeScript.
π Motivating Example
Provide a way to take this code:
function isFish(pet: Fish | Bird): pet is Fish {
return (pet as Fish).swim !== undefined;
}
if (!isFish(pet)) {
throw new Error('Pet is not a dish');
}
pet.swim();
and extract these lines into a function:
if (!isFish(pet)) {
throw new Error('Pet is not a dish');
}
giving something like this code:
function isFish(pet: Fish | Bird): pet is Fish {
return (pet as Fish).swim !== undefined;
}
function expectFish(pet: Fish | Bird): pet satisfies Fish | never {
if (!isFish(pet)) {
throw new Error('Pet is not a dish');
}
return true;
}
expectFish(pet);
pet.swim(); // Should not generate a type error
π» Use Cases
The motivation for this feature is to avoid having to write code like this in unit tests:
if (!isFish(pet)) {
throw new Error('Pet is not a fish');
}
expect(pet.swim()).toBeTruthy();
and instead be able to write code like this:
function expectFish(pet: Fish | Bird): pet satisfies Fish | never {
if (!isFish(pet)) {
throw new Error('Pet is not a fish');
}
}
expectFish(pet);
expect(pet.swim()).toBeTruthy();
I've made up the pet satisfies Fish | never
. Here's some alternative ideas for the new syntax:
pet is Fish === true | never
pet satisfies Fish === true | never
pet is Fish ? true | never
pet satisfies Fish ? true | never