Composable types
- Dominant language
- No language data
- Stars
- 328
- Forks
- 71
- PR merge metrics
- No merged PRs in 30d
Description
I propose that type names can be replaced with composed types, in either of the following forms:
* ` And ` -- intersection types
* ` Or ` -- union types
# Use cases:
* Multitype checking
* Use members from both type parts (intersection type only)
* Consolidate function overloads (union types only)
### Multitype checking
This syntax allows for checking either of two types (`Or`), or both of two types (`And`). Requires no changes to the `TypeOf Is ` statement, only an expansion of ``.
Instead of:
```vb
If TypeOf x Is String Or TypeOf x Is IEnumerable(Of Integer) Then
```
Use:
```vb
If TypeOf x Is String Or IEnumerable(Of Integer) Then
```
Instead of:
```vb
If TypeOf x Is MyClass And TypeOf x Is MyInterface Then
```
Use:
```vb
If TypeOf x Is MyClass And MyInterface Then
```
Parentheses are not required, because the compiler can differentiate between ` Or ` and ` Or `; but it's important that parentheses be allowed, to improve readability when needed:
```vb
Dim flag = True
If (TypeOf o Is String Or Number) Or flag Then
End If
```
### Use members from both type parts (intersection type only)
Define parameters / variables as an intersection of a class and an interface; allows using members from both without having to cast:
```vb
Class MyClass
Public I As Integer
End Class
Interface MyInterface
Public J As Integer
End Interface
Dim x As MyClass And MyInterface
Console.WriteLine(x.I)
Console.WriteLine(x.J)
```
### Consolidate function overloads (union types only)
Reduce the boilerplate function overloads needed for multiple types. Instead of this:
```vb
Sub PrintStrings(toPrint As IEnumerable(Of String))
For Each s In toPrint
Console.WriteLine(s)
Next
End Sub
Sub PrintStrings(toPrint As String)
PrintStrings({toPrint})
End Sub
```
Use this:
```vb
Sub PrintStrings(toPrint As IEnumerable(Of String) Or String)
If TypeOf toPrint Is String Then toPrint = {toPrint}
For Each s In toPrint
Console.WriteLine(s)
Next
End Sub
```
# Type aliases
VB.NET already has a syntax for type aliasing:
```vb
Imports MyType = Namespace.Type
```
This should support using composable types:
```vb
Imports MyType = Namspace.Type1 Or Namespace.Type2
Imports MyType1 = Namespace.Class1 And Namespace.Interface1
```
# Potential Issues
1. Some static flow analysis would make union types much more useful. The flow analysis would limit the type within a type check, or after an assignment (this is really just an extension of #172):
```vb
Sub PrintStrings(toPrint As IEnumerable(Of String) Or String)
If TypeOf toPrint Is String Then
'The compiler should be aware that at this point the object pointed to by toPrint must be of type String
toPrint = {toPrint} 'Even though the value of toPrint is of type String, the assignment to the toPrint variable is still allowed
'and from here on, toPrint is IEnumerable(Of String)
End If
For Each s In strings
Console.WriteLine(s)
Next
End Sub
```
2. There already exists a syntax for intersection types, when used with generic constraints:
Public Class MyClass(Of T As {IComparable, IDisposable})
End Class
However, I don't see how it can be extended for union types as well.
OTOH, I don't see any reason not to allow composite types in generic constraints:
Public Class MyClass(Of T As IComparable And IDisposable)
End Class
Public Class MyClass(Of T As IComparable Or List(Of Integer))
End Class
3. Is there CLR support for union and intersection types? (See F#.)
4. How could such members / classes be represented for compatibility with other languages? (Also see F#.)
5. How would reflection work with these types? (Again, see F#.)
# Contexts
Composable types should be allowed in the following contexts:
* `TypeOf` statement
* Parameters
* Local variables
* Return types
* Generic constraint definitions
* Generic parameters
They should not be allowed in the following contexts:
* `Inherits` -- For union types, to say that `A` inherits from `B` or from `C` is meaningless. For intersection types, also not, because VB.NET doesn't support multiple inheritance
* `Implements` -- The class cannot implement either interface `A` or interface `B`; it must implement both, so union types are irrelevant. Implementing an intersection types adds nothing over implementing each type separately.
# Links
* [TypeOf over multiple types](https://github.com/dotnet/vblang/issues/23)
* [Latest discussion of intersection / union types in C#](https://github.com/dotnet/csharplang/issues/399)
* Typescript's [union](https://github.com/Microsoft/TypeScript-Handbook/blob/master/pages/Advanced%20Types.md#union-types) and [intersection](https://github.com/Microsoft/TypeScript-Handbook/blob/master/pages/Advanced%20Types.md#intersection-types) types.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.