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

Add type guard for is.truthy and is.falsy #151

Merged
merged 2 commits into from
Jan 25, 2022

Conversation

zshannon
Copy link
Contributor

@zshannon zshannon commented Jan 16, 2022

Fixes #146 and not sure if adding the same Falsy guard to is.falsy helps there because I'm just using is.truthy as a .filter but happy to add the Falsy annotation to is.falsy too if helpful

@sindresorhus
Copy link
Owner

sindresorhus commented Jan 16, 2022

I think it would be better to participate in #146 first. There are unanswered questions there.

Although there are restrictions on using is.truthy() as a type guard function

but in what cases would it be useful though?

source/types.ts Outdated Show resolved Hide resolved
@sindresorhus
Copy link
Owner

It doesn't look like you ran the tests before submitting.

@zshannon zshannon force-pushed the truthy-type-narrowing branch from 83b0b02 to dfd6d4e Compare January 16, 2022 16:02
@zshannon zshannon force-pushed the truthy-type-narrowing branch from dfd6d4e to 12a6161 Compare January 16, 2022 16:04
@zshannon
Copy link
Contributor Author

It doesn't look like you ran the tests before submitting.

You're right, sorry about that, updated with passing tests. Also added 0n to Falsy.

Although there are restrictions on using is.truthy() as a type guard function

I don't follow what "restrictions on using is.truthy() as a type guard function" means so not sure how to add to the conversation there. I also don't know "in what cases would [is.falsy as a typeguard] be useful". But is.truthy as a typeguard (this PR) is something I use constantly so can easily speak to that if it's unclear :)

@sindresorhus
Copy link
Owner

I don't follow what "restrictions on using is.truthy() as a type guard function" means

// @younho9

@sindresorhus
Copy link
Owner

My comment about is.falsy clearly applies to is.truthy too. The gist of it is "The narrowing is still pretty wide.". How is such a wide narrowing more useful than unknown? What can you now use is.truthy for that was not possible before the type-guard?

@younho9
Copy link

younho9 commented Jan 17, 2022

I thought is.truthy has some restrictions in the following case.

export type Falsy = false | 0 | 0n | '' | null | undefined;

const isTruthy = <T>(value: T | Falsy): value is T => Boolean(value);
const isFalsy = (value: unknown): value is Falsy => !Boolean(value);

declare const number_: number;

if (isTruthy(number_)) {
    number_ // number
} else {
    number_ // never
}

if (isFalsy(number_)) {
    number_ // 0
} else {
    number_ // number
}

is.falsy could be useful to narrow falsy value from primitive type, but is.truthy is not.

I think using it with a filter could be one of use case.

@younho9
Copy link

younho9 commented Jan 17, 2022

Also, when value has falsy type, is.truthy couldn't find truthy value.

declare const falsyValue: null;

if (isTruthy(falsyValue)) {
    falsyValue // null, expected never
} else {
    falsyValue // never, expected null
}

if (isFalsy(falsyValue)) {
    falsyValue // null
} else {
    falsyValue // never
}

TypeScript Playground

@zshannon
Copy link
Contributor Author

I use isTruthy as a typeguard with filters everywhere, pattern is like this:

type Tipe = { ... }
const maybes: Array<Tipe | undefined | null> = await Promise.allSettled([ ... calls that may fail ... ]).map(({ value }) => value)
maybes.filter(isTruthy).map(X => { ... X is Tipe here ... })

I can guess from the defaults in unicorn that @sindresorhus is not a fan of passing eg isTruthy directly into .filter like this but it's still useful even with the extra maybes.filter(maybe => isTruthy(maybe)) characters ;)

@sindresorhus
Copy link
Owner

Ah, I get it now. So it's really just about narrowing away undefined and null.

@sindresorhus
Copy link
Owner

Also, when value has falsy type, is.truthy couldn't find truthy value.

Do you know why that happens?

@sindresorhus
Copy link
Owner

Seems like this change could be useful even with the mentioned limitations.

@sindresorhus
Copy link
Owner

@zshannon Could you also apply this to is.falsy?

@sindresorhus sindresorhus changed the title add type guard for is.truthy to narrow result Add type guard for is.truthy and is.falsy Jan 25, 2022
@sindresorhus sindresorhus merged commit 63d75d6 into sindresorhus:main Jan 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Proposal: is.falsy() as a type guard
3 participants