Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

'!' shouldn't cast the type predicate to boolean #20580

Closed
kujon opened this issue Dec 8, 2017 · 2 comments
Closed

'!' shouldn't cast the type predicate to boolean #20580

kujon opened this issue Dec 8, 2017 · 2 comments
Labels
Duplicate An existing issue was already created

Comments

@kujon
Copy link
Contributor

kujon commented Dec 8, 2017

TypeScript can currently infer the remainder of the type that has been narrowed down, without any issues:

const isError = <T>(value: T | Error): value is Error => value instanceof Error;

const foo = (value: string | number | Error) => {
    if (isError(value)) {
        return value.message; // number, because of the type guard
    } else {
        return value.toString(); // Everything that is not a number.
    }
}

When ! operator is used on the type predicate, the compiler casts it to boolean immediately.

const isError = <T>(value: T | Error): value is Error => value instanceof Error;

type Something = number;
type SomethingElse = string;

const getSomething = (): Something | Error => 42;
const getSomethingElse = (): SomethingElse | Error => Math.random() > 0.5 ? 'foo' : Error('bugger');

const loadsOfData = [
    getSomething(),
    getSomethingElse()
];

const allThingsFailed = loadsOfData.filter(isError); // Error[]
const allThingsSuccessful = loadsOfData.filter(elem => !isError(elem)); // (string | number | Error)[]

Because of this, you can often end in situations, where you write a lot of unnecessary code:

const isError = <T>(value: T | Error): value is Error => value instanceof Error;
const isNotError = <T>(value: T | Error): value is T => !(value instanceof Error);

Given that there seems to be the way TS represents a concept of Type less AnotherType, I'd be grand if the bang operator on type predicates worked the same way.

@ghost
Copy link

ghost commented Dec 8, 2017

Looks like a duplicate of #5101 (infer type predicate) and #18280 (negation types).
elem => !isError(elem) is a new function expression and has no explicit type declaration; and a type predicate is never inferred.
Since there's no way to represent a !Error type currently, you may have to write a filterNot or partition helper.

@ghost ghost added the Duplicate An existing issue was already created label Dec 8, 2017
@typescript-bot
Copy link
Collaborator

Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.

@microsoft microsoft locked and limited conversation to collaborators Jul 3, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

2 participants