TS
C#

TypeScript to C#

10 lessons

Progress0%
1Introduction: Two Languages, One Mind2Type Systems: Structural vs Nominal3Classes: Advanced Features4Generics and LINQ5Nullable Reference Types6Async/Await7Decorators to Attributes8Ecosystem9File I/O10Records and Pattern Matching
All Mirror Courses
TS
C#
Type Systems: Structural vs Nominal
MirrorLesson 2 of 10
Lesson 2

Type Systems: Structural vs Nominal

Type Systems

Introduction

In this lesson, you'll learn about type systems: structural vs nominal in C#. Coming from TypeScript, you already have a foundation for understanding this concept. We'll build on that knowledge while highlighting the key differences.

Mirror Card
TS
From TypeScript:

In TypeScript, you're familiar with type systems.

C#
In C#:

C# has its own approach to type systems, which we'll explore step by step.

The C# Way

Let's see how C# handles this concept. Here's a typical example:

C#
C# Example
// C#: NOMINAL typing
interface ISerializable {
    string Serialize();
}

// Must explicitly implement the interface
class Document : ISerializable {
    public string Serialize() => "{}";
}

void Save(ISerializable item) {
    item.Serialize();
}

Save(new Document()); // Must be ISerializable

Comparing to TypeScript

Here's how you might have written similar code in TypeScript:

TS
TypeScript (What you know)
// TypeScript: STRUCTURAL typing
interface Serializable {
  serialize(): string;
}

const obj = {
  serialize() { return "{}"; }
};

// Works — obj has the right shape
function save(item: Serializable) {
  return item.serialize();
}

save(obj); // OK without explicit declaration
Mirror Card
TS
From TypeScript:

You may be used to different syntax or behavior.

C#
In C#:

TypeScript structural: any object with the right shape satisfies the interface

Mirror Card
TS
From TypeScript:

You may be used to different syntax or behavior.

C#
In C#:

C# nominal: class must explicitly declare : IInterfaceName

Mirror Card
TS
From TypeScript:

You may be used to different syntax or behavior.

C#
In C#:

C# interface names conventionally start with I (IEnumerable, IDisposable)

Mirror Card
TS
From TypeScript:

You may be used to different syntax or behavior.

C#
In C#:

Both support multiple interface implementation

Step-by-Step Breakdown

1. Explicit Interface Implementation

In C#, a class must declare that it implements an interface with : IInterfaceName. The compiler then verifies all interface members are implemented.

TS
TypeScript
const myObj: Runnable = { run() {} }; // TS: shape is enough
C#
C#
class MyTask : IRunnable {
    public void Run() {} // C#: must declare
}
Rule of Thumb
C# interface names conventionally start with I to distinguish them from classes.

2. Multiple Interface Implementation

Both TypeScript and C# support implementing multiple interfaces. C# syntax mirrors TypeScript's & intersection closely.

TS
TypeScript
interface A { a(): void; }
interface B { b(): void; }
class C implements A, B { ... }
C#
C#
interface IA { void A(); }
interface IB { void B(); }
class C : IA, IB {
    public void A() {}
    public void B() {}
}

3. abstract class vs interface

C# abstract classes can have implementation (like TypeScript). Interfaces in C# 8+ can also have default implementations — a feature TypeScript lacks.

TS
TypeScript
abstract class Shape {
  abstract area(): number;
  describe() { return `area: ${this.area()}`; }
}
C#
C#
abstract class Shape {
    public abstract double Area();
    public string Describe() => $"area: {Area()}";
}

4. Type Aliases vs C# type

TypeScript type creates structural aliases. C# has no direct equivalent, but record and using type = ... (C# 12) provide similar conciseness.

TS
TypeScript
type UserId = number;
type Point = { x: number; y: number };
C#
C#
// C# 12 type alias:
using UserId = int;
// Record for data shapes:
record Point(double X, double Y);

Common Mistakes

When coming from TypeScript, developers often make these mistakes:

  • TypeScript structural: any object with the right shape satisfies the interface
  • C# nominal: class must explicitly declare : IInterfaceName
  • C# interface names conventionally start with I (IEnumerable, IDisposable)
Common Pitfall
Don't assume C# works exactly like TypeScript. While the concepts may be similar, the syntax and behavior can differ significantly.

Key Takeaways

  • C# is nominally typed — classes must explicitly implement interfaces
  • Interface names conventionally start with I in C#
  • C# abstract classes and interfaces work identically to TypeScript's
  • C# 12 using aliases and records provide TypeScript-like type alias conciseness
Rule of Thumb
The best way to learn is by doing. Try rewriting some of your TypeScript code in C# to practice these concepts.
PreviousNext