Do you want to work on this issue?
You can request for a bounty in order to promote it!
Improve type guard for `.all` #81
sindresorhus posted onGitHub
It would be nice if this worked:
const a = foo();
const b = bar();
// Both `a` and `b` is an `object`, but TS only knows they're `any`.
if (is.all(is.object, a, b)) {
// `a` and `b` is now known by TS as `object`
}
That’s possible I guess if there’s a way to know if the predicate is a type guard predicate
We don’t need to know it’s a type guard. We can just pass on what TS infers, maybe by using the infer
keyword: https://dev.to/miracleblue/how-2-typescript-serious-business-with-typescripts-infer-keyword-40i5
Someone mentions the "built in ReturnType<fn>
" type, this might help...
altho, following this issue:
interface Array<T> {
filter<U extends T>(pred: (a: T) => a is U): U[];
}
type Predicate<T> = (value: unknown) => value is T;
is.all = <T>(predicate: Predicate<T>, ...values: unknown[]): values is T[] =>
predicateOnArray(Array.prototype.every, predicate, values);
does this look right?
Looks good. Can you do a PR? :)
@issuehunt has funded $30.00 to this issue.
- Submit pull request via IssueHunt to receive this reward.
- Want to contribute? Chip in to this issue via IssueHunt.
- Checkout the IssueHunt Issue Explorer to see more funded issues.
- Need help from developers? Add your repository on IssueHunt to raise funds.
I ran into this recently and tried the suggested fix, it looks like this isn't possible generically.
export type Predicate<T = unknown> = (value: unknown) => value is T;
is.all = <T>(predicate: Predicate<T>, ...values: unknown[]): values is T[] =>
predicateOnArray(Array.prototype.every, predicate, values);
Gives the error A type predicate cannot reference a rest parameter.ts (1229)
.
Apparently it also isn't possible to do this manually for a few arguments. This is a compile error (and all the other variants I tried).
function test(a: unknown, b: unknown): (a is true) & (b is true) {
return true;
}
@Gerrit0 Thanks for looking into it!
to what line does this error refer to? is it thrown from predicateOnArray
or all
?
Did you try to update predicateOnArray
to have the second parameter be of type Predicate<T>
as well?
The error is caused by values is T[]
on all
. Updating Predicate
in the predicateOnArray
function unfortunately has no effect since the type guard is lost (changed to just be boolean
) when it is used in all
(or any
).
It is possible to achieve the goal in the OP with a different signature. This works as expected (no changes necessary for predicateOnArray
).
is.allArray = <T>(predicate: Predicate<T>, values: unknown[]): values is T[] =>
predicateOnArray(Array.prototype.every, predicate, values)
Any update on this issue ?
@nicosayer I think you can use is.array(value, predicate)
for that, does it help you?
@nicosayer I think you can use
is.array(value, predicate)
for that, does it help you?
I am not sure how this helps, can you elaborate ?
To make sure everything is clear, this is how I would summarize the issue:
What is currently happening:
let a: string | number
let b: string | number
if (is.all(is.string, a, b)) {
// `a` and `b` are of type string | number
}
What is actually expected:
let a: string | number
let b: string | number
if (is.all(is.string, a, b)) {
// `a` and `b` are of type string
}
@nicosayer yeah my bad, I've been out of context for a while and thought it would work, but it doesn't type-guard the specific array items