-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
Boolean() cannot be used to perform a null check #16655
Comments
It's not supported because no one has done the work to support it yet.
In general we don't account for this. Literally anything in the global scope could be mutated to be something different and it'd be insane to say Well you can't use I think we could replace the signature with
which is almost correct (it fails to do the right then in the I've literally never seen someone use |
I don't think there's any, apart from implicit vs. explicit type cast. I personally use it, because it makes type conversion to primitives consistent ( |
One common pattern using the boolean constructor is |
@Kovensky - that is a good point. const nonFalsy1 = [1, 2, undefined].filter(v => typeof v !== 'undefined');
const nonFalsy2 = [1, 2, undefined].filter(Boolean); |
@kujon You can make const nonFalsy1: number[] = [1, 2, undefined].filter(
<T>(v: T): v is Exclude<T, undefined> => typeof v !== 'undefined',
); It's a little bit verbose, but very flexible. |
This was reverted due to it causing a breaking change in 3.5. The simple repro looks like this: declare const Bullean: {
new(value?: any): Boolean;
<T>(value?: T): value is Exclude<T, false | null | undefined | '' | 0>;
};
declare const arr: any[];
// Was any[], now (3.5) unknown[]
const arr2 = arr.filter(Bullean); There might be something wrong in generic inference, but it's not yet clear. We'll need this scenario to work before adding it back in. |
I'm not sure what more I can do here? |
Just for interest, what is the reason that |
const arr = [1, 2, undefined];
const filtered: Array<number> = arr.filter(elem => elem != undefined);
const filtered2: Array<number> = arr.filter(Boolean);
// Type '(number | undefined)[]' is not assignable to type 'number[]'.
// Type 'number | undefined' is not assignable to type 'number'.
// Type 'undefined' is not assignable to type 'number'.
// Type '(number | undefined)[]' is not assignable to type 'number[]'. Both these scenarios right now still break. I found a temporary workaround with const workaround = arr.filter((elem): elem is number => elem !== undefined); However it would be nice not to need the type guard. Is there any hope for that :)? |
Another workaround (playground link): const values: Array<number | undefined> = [1, 2, undefined, 4, undefined, 6]
function nonNullish<V>(v:V): v is NonNullable<V> {
return v !== undefined && v !== null
}
values.filter(nonNullish).map(v => v.toFixed(5)) |
This adds an explicit type guard for truthiness. Generally you could use the `Boolean` constructor, but typescript doesn't treat that as a type guard right now (see [#16655](microsoft/TypeScript#16655)).
I think the "Awaiting more feedback" label can be removed, as tons of people seem to have this issue. |
Another workaround that I haven't seen mentioned is to create another Boolean object (Tested with TS 5.1.6) : type Falsy = false | 0 | "" | null | undefined
const _Boolean = <T extends any>(v: T): v is Exclude<typeof v, Falsy> => Boolean(v)
const filtered = [1, null, undefined, 2, 3].filter(_Boolean) // number[]
const orders = settled
.map((result) => (result.status === "fulfilled" ? result.value : false))
.filter(_Boolean) // array of fullfilled values It would be great if that was the default behaviour of Boolean |
This adds an explicit type guard for truthiness. Generally you could use the `Boolean` constructor, but typescript doesn't treat that as a type guard right now (see [#16655](microsoft/TypeScript#16655)).
This adds an explicit type guard for truthiness. Generally you could use the `Boolean` constructor, but typescript doesn't treat that as a type guard right now (see [#16655](microsoft/TypeScript#16655)).
This adds an explicit type guard for truthiness. Generally you could use the `Boolean` constructor, but typescript doesn't treat that as a type guard right now (see [#16655](microsoft/TypeScript#16655)).
did anyone found a way to make it work within a project so that Boolean() can act as a null check ? upd:
although, in my case next piece still errored byts:2345:
at the same time with no error
|
@SergeOlabin sadly that custom BooleanConstructor doesn't work when you do Would really be great this get this fixed from TS side. |
@RyanCavanaugh maybe this is known, but some time between when you wrote this in 2019 and today, this breaking change seems to have happened anyway. Playground link I'm doing my yearly rabbit-hole dive of why-can't-we-have- Here's another playground with that proposed fix applied as a module augmentation, along with some type tests for the edge cases/prior bugs reported over the years from this issue, #50387, mattpocock/ts-reset#168, and #31551. I put links to GitHub issue comments as inline comments in the code. Here's the augmentation to interface Array<T> {
// this overload already exists in lib/es5.d.ts, re-adding here to make sure the overloads are checked in the correct order
filter<S extends T>(predicate: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[];
// this is the proposed change to lib/es5.d.ts
filter<P extends (value: T, index: number, array: T[]) => unknown>(
predicate: P,
thisArg?: unknown,
): (P extends BooleanConstructor ? Exclude<T, null | undefined | 0 | false | ''> : T)[];
} What do you think? Can we have |
The boolean constructor is so useful for maps, JSX and in general far more readable than doing the double negation. @RyanCavanaugh @DanielRosenwasser @sheetalkamat could you please consider fixing this in one of the next versions? 🙏 |
This seems particularly strange with the new predicate inference in 5.5. If you do |
TypeScript Version: 2.4.0
Apologies for today's issue raising binge.
Code
Expected behavior:
Both examples compile.
Actual behavior:
The latter example fails w/
Object is possibly 'undefined'
.Explanation
To my knowledge
!!value
andBoolean(value)
are equivalent. I'm wondering what is the reason behind not supporting the second case. One reason I can think of would be an imported, non-typescript module, globally overriding it to something like:Boolean = (value) => !value
.The text was updated successfully, but these errors were encountered: