Skip to content

Generated Code

Every [TypedId] struct receives a complete value-type implementation via source generation. The generated code is visible in your IDE under the AnalyzersDeepstaging.Generators node.

Generated Members

Member Description
Value property The underlying backing value
Constructor new UserId(Guid value)
IEquatable<T> Value-based Equals, GetHashCode, ==, !=
IComparable<T> Value-based CompareTo, >, <, >=, <=
IFormattable Format-string overload of ToString
ISpanFormattable Span-based formatting (.NET 6+)
IParsable<T> Parse(string) and TryParse (.NET 7+)
ISpanParsable<T> Span-based parsing (.NET 7+)
IUtf8SpanFormattable UTF-8 span formatting (.NET 8+)
IUtf8SpanParsable<T> UTF-8 span parsing (.NET 8+, numeric types)
ToString() Returns the backing value as a string
Empty Static readonly field with the default/empty value
New() Factory method (Guid only — creates a v7 UUID)
Parse(string) Static parse method for all backing types
Implicit conversion From backing type → typed ID
Explicit conversion From typed ID → backing type
TypeConverter Always generated — enables ASP.NET model binding
var id = UserId.New();               // v7 UUID
var parsed = UserId.Parse("...");    // from string
var empty = UserId.Empty;            // Guid.Empty
Guid raw = (Guid)id;                 // explicit cast
UserId fromGuid = Guid.NewGuid();    // implicit conversion
bool eq = id == parsed;              // value equality

String Validation

String-backed IDs validate against null and empty strings in the constructor:

  • On .NET 7+ — uses ArgumentException.ThrowIfNullOrEmpty
  • On older targets — throws ArgumentNullException

This ensures that a string-backed typed ID always holds a meaningful value.

[TypedId(BackingType = BackingType.String)]
public readonly partial struct ExternalId;

var id = new ExternalId("ext-123");  // ✅ OK
var bad = new ExternalId("");        // ❌ throws ArgumentException

Usage Patterns

In Records and DTOs

public record OrderDto(OrderId Id, string Name, UserId CreatedBy);

As Dictionary Keys

With JsonConverter enabled, typed IDs work as JSON dictionary keys via generated ReadAsPropertyName / WriteAsPropertyName:

var lookup = new Dictionary<UserId, string>
{
    [UserId.New()] = "Alice"
};

var json = JsonSerializer.Serialize(lookup); // keys serialize as strings

In EF Core Models

With EfCoreValueConverter enabled:

[TypedId(Converters = IdConverters.EfCoreValueConverter)]
public readonly partial struct OrderId;

public class Order
{
    public OrderId Id { get; set; }
    public string Name { get; set; } = "";
}

// In DbContext.OnModelCreating:
modelBuilder.Entity<Order>()
    .Property(e => e.Id)
    .HasConversion<OrderId.EfCoreValueConverter>();