JV
TS

Java to TypeScript

10 lessons

Progress0%
1Introduction to TypeScript2Type Systems3Classes & OOP4Generics5Modules & Packages6Null Safety7Async vs Threads8Ecosystem9Advanced TypeScript Types10Build Tooling
All Mirror Courses
JV
TS
Type Systems
MirrorLesson 2 of 10
Lesson 2

Type Systems

Type Systems

Introduction

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

Mirror Card
JV
From Java:

In Java, you're familiar with type systems.

TS
In TypeScript:

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

The TypeScript Way

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

TS
TypeScript Example
// TypeScript - structural typing
let name: string = "Alice";
let age: number = 30;       // all numbers are number
let active: boolean = true;
let items: string[] = [];   // or Array<string>

interface Printable {
    print(): void;
}

// No "implements" needed if shape matches!
const doc = {
    print() { console.log("doc"); }
};
// doc is compatible with Printable automatically

Comparing to Java

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

JV
Java (What you know)
// Java - nominal typing
String name = "Alice";
int age = 30;
boolean active = true;
List<String> items = new ArrayList<>();

interface Printable {
    void print();
}

class Doc implements Printable { // must declare!
    public void print() { System.out.println("doc"); }
}
Mirror Card
JV
From Java:

You may be used to different syntax or behavior.

TS
In TypeScript:

TypeScript uses structural typing — if an object has the right shape, it's compatible, no explicit declaration needed

Mirror Card
JV
From Java:

You may be used to different syntax or behavior.

TS
In TypeScript:

Java uses nominal typing — a class must explicitly say 'implements Interface' to be compatible

Mirror Card
JV
From Java:

You may be used to different syntax or behavior.

TS
In TypeScript:

Java has int, long, float, double; TypeScript has a single number type for all numeric values

Mirror Card
JV
From Java:

You may be used to different syntax or behavior.

TS
In TypeScript:

Java String (capital S) vs TypeScript string (lowercase)

Mirror Card
JV
From Java:

You may be used to different syntax or behavior.

TS
In TypeScript:

TypeScript generics use similar <T> syntax: Array<string> or string[]

Step-by-Step Breakdown

1. Structural vs Nominal Typing

This is the most important conceptual difference. TypeScript checks the shape of an object, not its declared type name.

JV
Java
interface Flyable { void fly(); }
class Bird implements Flyable { // must declare
    public void fly() { }
}
TS
TypeScript
interface Flyable { fly(): void; }

// Works WITHOUT "implements Flyable"!
const bird = {
    fly() { console.log("flap"); },
    sing() { console.log("tweet"); }
};

function takeOff(f: Flyable) { f.fly(); }
takeOff(bird); // ✓ — bird has fly(), so it's Flyable
Rule of Thumb
In TypeScript, focus on what an object can DO, not what it's declared AS.

2. Number is One Type

Java has separate integer and floating-point types. TypeScript has a single number type covering all numeric values.

JV
Java
int count = 10;
double price = 9.99;
long bigNum = 9_000_000_000L;
TS
TypeScript
let count: number = 10;
let price: number = 9.99;
let bigNum: number = 9_000_000_000;

// For very large integers, use bigint:
let huge: bigint = 9_000_000_000_000n;
Common Pitfall
JavaScript numbers are IEEE 754 doubles. Integers larger than 2^53 lose precision — use bigint for those.

3. Union and Literal Types

TypeScript can express types Java cannot — a variable can be one of several specific types or values.

TS
TypeScript
// Union type — string OR number
let id: string | number = "abc-123";
id = 42; // also valid

// Literal type — only these exact values
type Direction = "north" | "south" | "east" | "west";
let dir: Direction = "north";
// dir = "up"; // compile error!

// Optional — string or undefined
let nickname: string | undefined;

4. Type Inference

TypeScript infers types from initial values, so you rarely need to annotate every variable.

JV
Java
String name = "Alice"; // must annotate
int count = 0;
TS
TypeScript
let name = "Alice"; // inferred: string
let count = 0;      // inferred: number
let flags = [true, false]; // inferred: boolean[]

// Annotate when inference isn't enough:
let result: string | null = null;

Common Mistakes

When coming from Java, developers often make these mistakes:

  • TypeScript uses structural typing — if an object has the right shape, it's compatible, no explicit declaration needed
  • Java uses nominal typing — a class must explicitly say 'implements Interface' to be compatible
  • Java has int, long, float, double; TypeScript has a single number type for all numeric values
Common Pitfall
Don't assume TypeScript works exactly like Java. While the concepts may be similar, the syntax and behavior can differ significantly.

Key Takeaways

  • TypeScript uses structural typing — shape matters, not declared names
  • All numeric types collapse to number (use bigint for huge integers)
  • Union types (string | null) express optional and multi-type values
  • Type inference means you don't need to annotate every variable
Rule of Thumb
The best way to learn is by doing. Try rewriting some of your Java code in TypeScript to practice these concepts.
PreviousNext