feat(15048): One-sided Type Predicates #52255
Draft
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes #15048
Why not nominal type (a.k.a. type brand/tag)? It is excessive, and to avoid the trouble people would instead write something like
((v): v is number => Number.isInteger(v))(v) && (() => true)()
, given that it just works. It looks bad when hovering over the variables too, especially if there are multiple layers of type guards.Particularly for the built-in lib, we don't want something like
isInteger(number: unknown): number is number & { readonly integer: unique symbol };
, so this is the feasible solution.Ultimately I would also like to implement negative predicate and predicate with non-boolean return value such that an overload for
{ReadonlyArray, Array}.some
likesome<S extends T>(predicate: (value: T, index: number, array: T[]) => !(value is subtypeof S if truthy), thisArg?: any): !(this is subtypeof S[]);
could be added to the built-in lib, which addresses #46650 and #47574.The exact syntax is not confirmed, and is open to discussion.