-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Add support for type guarding to if statements #53201
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
Comments
Duplicate of #41710 |
Head & open issue: #6474 |
@brandonmcconnell theoretically it's a good idea, to remove function-only guards limitation. In the reality, more or less meaningful check + 'obj is' + type name will lead to extremely long, unreadable 'if' statements: instead of read guard name and go next you have to go trough visual garbage and find 'is xxx' statement to understand code logic. As a result, we will have language feature doomed to be permanently banned in various linters / style guides due to above reason. |
@koshic I don't think the syntax would be banned as you mentioned. I could certainly see the syntax being used in ways that make expressions harder to read but that's not so different from any convention in JS or TS, or programming general for that matterβ ternaries, overrides, etc. In cases where an if-statement might get too long, it would likely be recommended to move the condition into its own variable as I did in my first "after" example, above: function iterateOver<T>(obj: Iterable<T> | ArrayLike<T>, expose: Function) {
const isIterable = typeof (obj as Iterable<T>)[Symbol.iterator] === 'function';
if (isIterable): obj is Iterable<T> {
// some logic here
} else {
// some logic here
}
} |
@brandonmcconnell yeah, it will work - but there is no real difference between if (isIterable): obj is Iterable<T> {
// some logic here
} else {
// some logic here
} and if (isIterable(obj) {
// some logic here
} else {
// some logic here
} Also, 'dedicated variable' pattern will split guard into 2 independent parts, which is unsafe: variable declared without any information about expected type. Obviously, check logic & expected type should be defined inside single syntax construct (guard function, or extended 'if' statement from your proposal). So, the chain will be a bit longer: 'do not use long guards in conditions -> extract them to variables -> keep variables near appropriate condition -> do we really need 3 eslint rules for that feature? let's ban it instead'. What I want to say - every new feature should be fine balanced: flexibility, readability, maintainability & safety (== foolproof) are equal important. From my standpoint, ability to mark boolean variable with 'obj is Xxx' (and check that metadata in conditions) is more realistic: no visual garbage near conditions, single construct, very similar to existing guard functions. Thx! |
Great feedback. I appreciate you putting so much time into this. My only counter-thought would be that the same vulnerability you mentioned is also present with functional type guards. |
Hmm, we can't separate guard function definition and 'o is Xxx' statement. Or may be I missed something obvious? |
I think this is a good idea, but related to #54270, you may want the ability to narrow within the if ([condition]) {
} else: obj is Iterable<T> {
} In addition, I would expand this to all scopes, because you should also be able to do: while ([condition]): obj is Iterable<T> {
} and: do: obj is Iterable<T> {
} while ([condition])
// OR?
// do {
// } while ([condition]): obj is Iterable<T> This breaks down with ternary statements, but at that level it adds too much complexity, and the |
If you don't want to complicate all the above control flow statements, you should just be able to do: do {
assert obj is Iterable<T>
} while ([condition])
if ([condition]) {
} else {
assert obj is Iterable<T>
} Right now, it's sometimes very complicated getting TypeScript to magically narrow a type within a scope. Ideally this could just be triggered manually. |
Suggestion
π Search Terms
type guard guarding assertion
β Viability Checklist
My suggestion meets these guidelines:
β Suggestion
This proposal introduces a new feature that would allow developers to use type guard statements with if-statements rather than only with functions. This feature would provide a more concise and expressive syntax for type guards, making code easier to read and maintain.
π Motivating Example
With the proposed feature, developers could use the
is
keyword directly within an if-statement to perform a type guard. For exampleβ¦Before β requires separate function for type guarding
After β can handle type guarding inline via if statement
** this could just as easily be rewritten to get rid of the
isIterable
placeholder altogether, like this:π» Use Cases
Currently, if developers want to use a type guard to narrow down the type of a value within an if statement, they need to define a separate function (AFAIK) that returns a boolean value indicating whether the value is of a certain type. This approach can be cumbersome and can lead to code that is harder to read and understand.
The text was updated successfully, but these errors were encountered: