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

Proposal: Predicate inferer #973

Open
1 task done
emmbm opened this issue Nov 1, 2024 · 5 comments
Open
1 task done

Proposal: Predicate inferer #973

emmbm opened this issue Nov 1, 2024 · 5 comments

Comments

@emmbm
Copy link

emmbm commented Nov 1, 2024

Type description + examples

With typescript now supporting predicate inference for guard functions without the need for explicitly specifying a is clause, it could be interesting to provide a simple helper that allows to get the inferred predicate for any guard function.

Ex.:

function isValid(value: string | number | null | undefined | false) {
  return value != null && value !== false;
} // : value is string | number

type Valid = Predicate<typeof isValid> // string | number

Type source

export type Predicate<T> = T extends (x: any) => x is infer U ? U : never;

Search existing types and issues first

  • I tried my best to look for it

Upvote & Fund

  • We're using Polar.sh so you can upvote and help fund this issue.
  • The funding will be given to active contributors.
  • Thank you in advance for helping prioritize & fund our backlog.
Fund with Polar
@sindresorhus
Copy link
Owner

Sounds useful, but the name is slightly confusing. The type extracts the inferred guard type, but a name like Predicate makes it sound like it's for making predicates. Maybe something like GuardType or ExtractGuard?

@emmbm
Copy link
Author

emmbm commented Nov 2, 2024

I agree Predicate is probably not the best naming, but I don't think derivatives of Guard sound right either since the guard is technically the check, not it's resulting assertion. Maybe GuardedType or just Guarded?

@fregante
Copy link
Collaborator

fregante commented Nov 4, 2024

This type would be similar to ReturnType so maybe it should follow its naming.

@Emiyaaaaa
Copy link
Collaborator

Looks interesting, are there any use cases?

@emmbm
Copy link
Author

emmbm commented Nov 25, 2024

@Emiyaaaaa rather than having to rely on manually maintaining consistency across explicit predicates and implementations, it allows to derive types from guard function implementations, the latter being less error-prone.

For example:

// Before

type Valid = string | number | null // Let's say a dev decided to add null to this union.

// When declared explicitly, the predicate can diverge from the actual implementation if not cautious.
function isValid(value: string | number | null | undefined | false): value is Valid {
  return value != null && value !== false;
}
// After

function isValid(value: string | number | null | undefined | false) {
  return value != null && value !== false;
}

type Valid = Predicate<typeof isValid> // This will always be up to date with the guard implementation.

Use cases include typing function params based on guard implementations or extracting type from data parsing functions without having to explicitly repeat types now adequately inferred by ts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants