TypeScript Basics for C# Developers

If you’re a C# developer dipping your toes into frontend development, TypeScript will feel surprisingly familiar. It’s JavaScript with types, and Microsoft designed it with C# developers in mind. Here’s what you need to know.

Why TypeScript?

JavaScript is… flexible. Too flexible sometimes. TypeScript adds compile-time type checking, which catches bugs before they hit production. If you’ve ever debugged “undefined is not a function” at 2 AM, you’ll appreciate this.

Types: What You Already Know

// Basic types - just like C#
let name: string = "John";
let age: number = 30;
let isActive: boolean = true;
let items: string[] = ["one", "two", "three"];

// Any - the escape hatch (use sparingly!)
let mystery: any = 42;
mystery = "now I'm a string";

Interfaces vs Classes

In C#, we use interfaces for contracts and classes for implementation. TypeScript is similar, but interfaces are more powerful:

// Interface - shape of an object
interface User {
    id: number;
    name: string;
    email?: string;  // Optional property
    readonly createdAt: Date;  // Read-only
}

// Class - with implementation
class UserService {
    private apiUrl: string;
    
    constructor(apiUrl: string) {
        this.apiUrl = apiUrl;
    }
    
    async getUser(id: number): Promise<User> {
        const response = await fetch(`${this.apiUrl}/users/${id}`);
        return response.json();
    }
}

Functions

// Typed function
function greet(name: string, greeting?: string): string {
    return `${greeting || 'Hello'}, ${name}!`;
}

// Arrow functions (like C# lambdas)
const add = (a: number, b: number): number => a + b;

// Callback types
function processItems(items: string[], callback: (item: string) => void): void {
    items.forEach(callback);
}

Generics

Generics work almost identically to C#:

// Generic function
function firstOrDefault<T>(items: T[], predicate: (item: T) => boolean): T | undefined {
    return items.find(predicate);
}

// Generic interface
interface Repository<T> {
    getById(id: number): Promise<T>;
    getAll(): Promise<T[]>;
    save(item: T): Promise<void>;
}

// Usage
const user = firstOrDefault(users, u => u.id === 1);

Key Differences from C#

  • Structural typing: TypeScript uses duck typing. If it has the right shape, it’s compatible
  • No method overloading: Use optional parameters or union types instead
  • Null handling: null and undefined are different. Enable strict null checks
  • Enums: Similar but with some JavaScript quirks

Recommended tsconfig.json

{
  "compilerOptions": {
    "target": "ES2017",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  }
}

Enable strict mode from day one. It catches so many bugs.

References


Discover more from C4: Container, Code, Cloud & Context

Subscribe to get the latest posts sent to your email.

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.