-
Notifications
You must be signed in to change notification settings - Fork 3k
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
[TS] filter(Boolean)
loses type information, TypeScript 3.5 makes it worse
#4959
Comments
Thanks. This is worthy of a linting rule that includes a fixer, IMO. |
Seems to be solved by adding the following overload signature (before the others): export function filter<T>(predicate: BooleanConstructor): OperatorFunction<T, NonNullable<T>>; ATM, I cannot see any downsides to this. The problem also affects IIRC, |
Hmm, I did a small test with this change over our codebase and while some issues go away, there is another problem with type inference. In the simplest form this looks like: interface I {
a: string | null;
}
let i$: Observable<I> = of();
let s$: Observable<string> = i$.pipe(
map(i => i.a), // type-error here
filter(Boolean)
); see It appears that TS's inferencer works "backwards" from the declared type - |
@alxhub came up with a fix for this situtation, by explicitly adding the function filterB<T>(
predicate: BooleanConstructor
): OperatorFunction<T|null|undefined, NonNullable<T>> {
return filter(predicate);
} I will do another test to see if this fixes most breakages. |
* fix(types): add Boolean signature to filter Closes #4959 * chore: add test using comment snippet #4959 (comment) #4968
@rkirov i'm afraid that what you've outlined above doesn't really have a fix that I can see. Were you able to work around it on your end? |
I tested the change outlined above in g3 and it passes, so we should be good. Also we upgraded to TS3.5, by removing all offending My only hesitation is that with the change, one will always be allowed to do a filter boolean on a non-nullable type: of(1,2,3).pipe(filter(Boolean)); // it would nice if that errs. There is an argument for wanting that to be statically disallowed, but one can't have it all. Not having hidden 'any's any longer is a major win. |
|
Right, I should have said " |
What is the consensus on what @rkirov suggested above regarding the inclusion of function filterB<T>(
predicate: BooleanConstructor
): OperatorFunction<T|null|undefined, NonNullable<T>> {
// ~~~~~~~~~~~~~~~~
return filter(predicate);
} Is this something we should be including in this change? @benlesh ? IMO, this is okay, if it fixes a problem. |
I didn't realize it didn't land with that modification. Without it, it will break internal users and with it there are no errors. |
@benlesh ^ |
Bug Report
More of a heads up, than a bug report, but this has been a major PITA for upgrading Google internal to TS 3.5, so I wanted to have a discussion here too.
Current Behavior
With TS3.4
pipe(filter(Boolean))
loses type information, everything after it is of typeany
. See stackblitz below:The type of Boolean in
lib.d.ts
isWith TS3.5 Boolean is typed as
https://github.com/microsoft/TypeScript/blob/master/lib/lib.es5.d.ts#L536
However, in most cases it appears
<T>
is not inferrable (I don't blame TS, this is really round-about), so TS3.5 pick the new defaultunknown
, which in turn makes the type for the next operationunknown
from previouslyany
causing many compilation failures.Reproduction
https://stackblitz.com/edit/rxjs-erah82
Possible Solution
I have been recommending replacing
filter(Boolean)
with the following more explicit workaroundfilter((x): x is OutputType => !!x)
whereOutputType
is explicitly spelled out the expected type in the next operation in the chain.Or maybe once microsoft/TypeScript#16655 (comment) lands
filter(Boolean)
will just work for Rxjs.The text was updated successfully, but these errors were encountered: