Proposal: Type narrowing methods | Method matchers - TypeScript-style Type Guards #8464
Unanswered
Hookyns
asked this question in
Language Ideas
Replies: 1 comment 3 replies
-
Having the data influence the typing feels like a very TypeScript approach, which works given that types don't actually exist. I don't quite see how that works with static typing in C#/.NET as the underlying type is entirely independent of the values of any of the members of the type, and it's up to constructor code to ensure that you can't get an instance of a type that violates that contract. Pattern matching over union types is definitely being considered, but that would be based on the type hierarchy and/or the tag. So, for the suggested use case, I would expect that you could do the following: IResult<Pizza> result = _pizzaMaker.MakeQuattroFormaggi();
result switch {
Ok(var value) => DoSomethingWith(value),
Error(var error) => DoSomethingWithError(error)
} |
Beta Was this translation helpful? Give feedback.
3 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Motivation
In recent years, the trend has shifted towards stronger type safety and combating nullability issues. In C#, we now have the nullability, along with
init
andrequired
. However, I still see a gap when it comes to a higher-level feature that could significantly improve code design: TypeScript-style Type Guards.Type Guards allow for more precise and expressive types, enabling us to refine a type based on a condition. Instead of having numerous nullable properties—some of which may or may not be null depending on the context—we could have a single base type that can be narrowed into a more specific type using a Type Guard. This approach would provide clearer constraints on what is non-nullable and what is not, resulting in cleaner and more maintainable code.
A Problem
Let's consider a simple example using a Result object:
In the generic
IResult<TValue>
interface, theValue
property should be non-nullable and propertyErrors
should be empty (or ideally, the property should not exist at all) when theIsOk
property istrue
. Otherwise,Value
should benull
(or ideally, the property should not exist at all) andErrors
should contains errors.Solution With Current Features
We are able to solve this simple example with one of the special attributes like this:
Usage
While these attributes work, they feel like a workaround and are not widely known or used. Additionally, they only cover a limited number of common scenarios.
Strongly-Typed Declaration
So there are no redundant properties, no nullable types.
Usage
Code written with this strongly-typed declaration can become cumbersome. It may require a significant amount of boilerplate code, especially in more complex scenarios, and forces developers to explicitly specify all types, making it far from user-friendly. As a NuGet package author, you cannot simply include this in your library; instead, you must educate your users on how to write conditions to achieve the intended results.
Design
I propose introducing the ability to define pattern matching directly on methods, allowing it to be utilized when calling those methods.
Method Declaration
Basic Syntax
where
constraints:is
:In the match expression/specifier/whatever we can use
this
or a method parameter.else
clauseUsage
I came up with two possible approaches.
Variant 1 - "override" type of the variable in the scope
I like this approach the most, but I doubt it has a strong chance of being accepted.
Variant 2 - pattern matching style
Notes
What do you think about this idea?
Beta Was this translation helpful? Give feedback.
All reactions