MultiType.NET.Core 1.0.1

dotnet add package MultiType.NET.Core --version 1.0.1
                    
NuGet\Install-Package MultiType.NET.Core -Version 1.0.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="MultiType.NET.Core" Version="1.0.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="MultiType.NET.Core" Version="1.0.1" />
                    
Directory.Packages.props
<PackageReference Include="MultiType.NET.Core" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add MultiType.NET.Core --version 1.0.1
                    
#r "nuget: MultiType.NET.Core, 1.0.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#addin nuget:?package=MultiType.NET.Core&version=1.0.1
                    
Install as a Cake Addin
#tool nuget:?package=MultiType.NET.Core&version=1.0.1
                    
Install as a Cake Tool

๐Ÿšฆ MultiType.NET

Type-safe, zero-allocation discriminated unions for modern .NET
Bring TypeScript-style union types to C# โ€” safer than object, cleaner than if, and built for real-world APIs and models.

Any<int, string> result = "hello";

NuGet Downloads


๐Ÿง  What Is a Union Type?

A union type lets a value be one of multiple specified types โ€” like this in TypeScript:

let result = number | string | null

// C# with MultiType.NET
Any<int, string> result = "hello";

MultiType.NET brings that idea to C# with full support for:

  • โœ… Type-safe access (Is<T>(), As<T>(), Match)
  • โœ… JSON (de)serialization
  • โœ… Zero boxing
  • โœ… ASP.NET API compatibility
  • โœ… Source generation for no-boilerplate code

โœจ Features Overview

Category Features
โœ… Matching Match, TryMatch, Switch, SwitchAsync, SwitchOrDefault
๐Ÿ” Mapping Map, MapAsync, MapSafe, MapValue, MapAny, MapWithContext, MapOrDefault, MapWhere
๐Ÿ” Selection Select, TrySelect, SelectAsync, SelectAsyncOrDefault, SelectWithContext, SelectWhere
๐Ÿ“ฆ Extraction GetTn, TryGetTn, GetTn(out remainder), Deconstruct(...)
๐Ÿง  Introspection ActualType, AllowedTypes, IsNull, ToString()
โš™๏ธ Construction From, TryFrom, FromTn, implicit/explicit operators
๐Ÿ“ค Serialization Native System.Text.Json support (global or attribute-based)
๐Ÿง‘โ€๐Ÿ’ป API-Ready Works with Controllers & Minimal APIs
๐Ÿงฉ Generator Auto-generates union types via [GenerateAny] or Any<T1..Tn>
๐Ÿงฉ Model Binding All types are Controller / Minimal-API Binding Ready

๐Ÿš€ Get Started

๐Ÿ“ฆ Install Core Library

dotnet add package MultiType.NET.Core

This gives you:

  • Any<T1..T16> prebuilt types
  • Core features like Match, Map, Switch, TryMatch, ...etc
  • JSON support via converter factory

๐Ÿ”ง Add Optional Source Generators

Package Description
MultiType.NET.Generator Adds [GenerateAny(typeof(...))] support
MultiType.NET.SourceGenerator Enables Any<T1..Tn> (over 16 types), JSON support, API integration
dotnet add package MultiType.NET.Generator

This allow you to generate a custom types with [GenerateAny], for more details MultiType.NET.Generator attribute.

[GenerateAny(typeof(string), typeof(MyType))]
public partial struct MyCustomType{}

This will generate MyCustomType with all MultiType APIs.

Need to generate Any<T17, ..., Tn>?

Install the official CLI generator:

dotnet tool install --global MultiType.NET.SourceGenerator

Then run:

multitypegen --maxArity 50 --project PATH_TO_TARGET_PROJECT.csproj

for more details and documentation MultiType.NET.SourceGenerator CLI


๐Ÿ’ก Learn by Example

Any<int, string, DateTime> result = "hello";

string output = result.Match(
    i => $"Int: {i}",
    s => $"String: {s}",
    d => $"Date: {d:yyyy-MM-dd}"
);
// Using generic Any<T1, T2, T3> directly from body
[HttpPost("process-multi-type")]
public async Task<IActionResult> ProcessMultiTypeData(
    [FromBody] Any<int, string, DateTime> requestData)
{
    // Example usage: requestData.Match(...)
    return Ok();
}

// Using generic Any<T1, T2, T3> from query string (less typical, but possible)
[HttpGet("query-multi-type")]
public async Task<IActionResult> QueryMultiTypeData(
    [FromQuery] Any<int, string, DateTime> queryData)
{
    return Ok();
}
if (result.TryGetT1(out var i, out var remainder))
    Console.WriteLine($"Was int: {i}");
else
    Console.WriteLine($"Not an int: {remainder}");
var summary = result.Select(
    i => $"# {i}",
    s => s.ToUpperInvariant(),
    d => d.ToShortTimeString()
);

๐Ÿงฑ Creating Any Values

MultiType.NET offers multiple ways to construct union values.

โœ… From(...) โ€” dynamic dispatch

object raw = 123;
var value = Any<int, string, DateTime>.From(raw);

๐Ÿ’ก Throws if the value is not one of the allowed types.

โœ… TryFrom(...) โ€” safe version

if (Any<int, string>.TryFrom(someValue, out var result))
{
    // Use result
}

โœ… FromTn(...) โ€” type-specific creation

var a = Any<int, string, bool>.FromT1(42);
var b = Any<int, string, bool>.FromT2("hello");

๐Ÿ’ก These are especially useful for code generation, dynamic input handling, or overload clarity.

โœ… Implicit Operators

Any<int, string> v1 = 5;
Any<int, string> v2 = "done";

๐Ÿ“ฆ JSON Serialization

MultiType.NET works seamlessly with System.Text.Json without any manual changes.

โœ… Per-type registration

public readonly partial struct MyUnionType;

๐Ÿงช Example

var options = new JsonSerializerOptions { WriteIndented = true };
string json = JsonSerializer.Serialize(Any<int, string>.From(123), options);

๐Ÿ’ก JSON output includes both the value and the represented type.


๐Ÿงฉ Custom Types with [GenerateAny]

โš ๏ธ Requires MultiType.NET.Generator installed.

[GenerateAny(typeof(int), typeof(string), typeof(Guid))]
public partial struct Payload;
// POST endpoint accepting Payload from body
[HttpPost("submit-payload")]
public async Task<IActionResult> SubmitPayload(
    [FromBody] Payload payload)
{
    // payload.Match(...)
    return Ok();
}

// GET endpoint accepting Payload from query
[HttpGet("search")]
public async Task<IActionResult> SearchPayload(
    [FromQuery] Payload query)
{
    return Ok();
}

Payload payload = Guid.NewGuid();

payload.Match(
    i => Console.WriteLine($"Int: {i}"),
    s => Console.WriteLine($"Str: {s}"),
    g => Console.WriteLine($"Guid: {g}")
);

** More advanced Type**

[GenerateAny(typeof(Success), typeof(Warning), typeof(Error), typeof(Info))]
public partial struct StatusType
{
    public static StatusType From(string value) => value.ToLowerInvariant() switch
    {
        "success" => new Success(),
        "warning" => new Warning(),
        "error" => new Error(),
        "info" => new Info(),
        _ => throw new ArgumentException("Invalid status", nameof(value))
    };

    public bool IsSuccess => this.Is<Success>();
    public bool IsWarning => this.Is<Warning>();
    public bool IsError => this.Is<Error>();
    public bool IsInfo => this.Is<Info>();

    public readonly struct Success { }
    public readonly struct Warning { }
    public readonly struct Error { }
    public readonly struct Info { }
}

โš™๏ธ How It Works (Behind the Scenes)

  • Any<T1, ..., Tn> is a readonly struct with internal value/ref handling.
  • Tracks active type via TypeIndex
  • Source generators:
    • Generate custom union types with all logic
    • Auto-wire JSON support
    • Add full method surface (Match, Map, Select, etc.)

๐Ÿงช Real-World Use Cases

Use Case Example
โœ… API Results Any<SuccessDto, ErrorDto>
๐Ÿง‘โ€โš–๏ธ Workflow Results Any<Approved, Rejected, Escalated>
๐Ÿง  State Modeling Any<Draft, Submitted, Published>
๐Ÿงพ Flexible Inputs Any<string, int, bool>
๐Ÿ”„ Retry Backoff Any<RetryLater, Fail, Success>

๐Ÿ“ Project Structure

Project Description
MultiType.NET.Core Runtime types and logic
MultiType.NET.Generator [GenerateAny] source generation
MultiType.NET.SourceGenerator JSON + Any<T1..Tn> generation

๐Ÿ“˜ Documentation

Resource Link
๐Ÿ” Advanced Features docs/AdvancedFeatures.md
๐Ÿง  Generator Guide docs/SourceGenerators.md
๐Ÿ’ก Integration Tips docs/Integration.md

๐Ÿ™Œ Contributing

Contributions, issues, and PRs are welcome!
See CONTRIBUTING.md to get started.


๐Ÿ“„ License

MIT โ€” LICENSE


Because type safety shouldn't be optional.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net8.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.1 115 7/2/2025