Skip to content

Instantly share code, notes, and snippets.

@pmendonca
Created December 24, 2025 13:11
Show Gist options
  • Select an option

  • Save pmendonca/4ab77c10d202e94add95dfae6ceaae0b to your computer and use it in GitHub Desktop.

Select an option

Save pmendonca/4ab77c10d202e94add95dfae6ceaae0b to your computer and use it in GitHub Desktop.
Typestate
namespace ExplicitTypes;
public interface IElementType { }
public interface IPokemon { int Id { get; } string Name { get; } }
public sealed class Fire : IElementType { }
public sealed class Water : IElementType { }
public sealed class Electric : IElementType { }
public sealed class Flying : IElementType { }
public sealed class None : IElementType { }
public sealed record Pokemon<T1, T2>(int Id, string Name) : IPokemon
where T1 : IElementType
where T2 : IElementType;
public static class Dex
{
public static Pokemon<Fire, None> Charmander() => new(4, "charmander");
public static Pokemon<Water, None> Squirtle() => new(7, "squirtle");
public static Pokemon<Electric, Water> Lanturn() => new(171, "lanturn");
public static Pokemon<Water, Flying> Gyarados() => new(130, "gyarados");
}
public sealed class WaterMember
{
public readonly IPokemon _pokemon;
private WaterMember(IPokemon pokemon) => _pokemon = pokemon;
public static WaterMember From<T2>(Pokemon<Water, T2> p)
where T2 : IElementType => new(p);
public static WaterMember From<T1>(Pokemon<T1, Water> p)
where T1 : IElementType => new(p);
}
public sealed class WaterTeam
{
public readonly List<WaterMember> _members = new();
public void Add(WaterMember m) => _members.Add(m);
}
public class Program
{
public static void Main()
{
var team = new WaterTeam();
team.Add(WaterMember.From(Dex.Lanturn())); // ✅
team.Add(WaterMember.From(Dex.Gyarados())); // ✅
team.Add(WaterMember.From(Dex.Charmander())); // ❌
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment