mediamonks / isntnt

A collection of composable JavaScript runtime type predicates with TypeScript type guard declarations
Other
6 stars 2 forks source link

Consider making predicate values generic #4

Open psimk opened 3 years ago

psimk commented 3 years ago

Currently the value argument for predicates is hardcoded to be unknown. This is fine for simple use cases like using predicates in if statements example :arrow_down:

const foo: null | number = null;
if(isSome(foo)) {
   foo; // now it's only of type 'number'
}

However, using predicates in methods and functions which use generics, TS can't correctly infer the type from the predicate.

const foo = [null, 1, null, 2, null]; // (number | null)[]

const cleanFoo = foo.filter(isSome); // still (number | null)[]

From what I can gather, making the value argument a generic fixes the above

function isSome<T>(value: T): value is Some<T> {
return value != null && value === value;
}

const foo = [null, 1, null, 2, null]; // (number | null)[]

const cleanFoo = foo.filter(isSome); // now correctly typed as number[]

TS playground

This example is only for isSome, but I imagine that this improvement could be added to most if not all predicates.

ThaNarie commented 3 years ago

but I imagine that this improvement could be added to most if not all predicates Definitely not "all", since there are some explicit return types that are fairly strict.

But even things like either('foo', 'bar') that normally narrows from unknown to 'foo' | 'bar' could benefit if the input is already typed as 'foo', to just return 'foo'?

So I like this approach.