TS
JV

TypeScript to Java

10 lessons

Progress0%
1Introduction: Compiler to JVM2Type Systems: Structural vs Nominal3Classes & OOP4Generics5Modules to Packages6Null Safety7Async to Threads8Ecosystem9Exception Handling10Collections and Stream API
All Mirror Courses
TS
JV
Generics
MirrorLesson 4 of 10
Lesson 4

Generics

Generics

Introduction

In this lesson, you'll learn about generics in Java. 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 generics.

JV
In Java:

Java has its own approach to generics, which we'll explore step by step.

The Java Way

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

JV
Java Example
public static <T> T identity(T value) {
    return value;
}

// Generic class
public class Box<T> {
    private T value;

    public Box(T value) { this.value = value; }

    public <U> Box<U> map(Function<T, U> fn) {
        return new Box<>(fn.apply(value));
    }
}

// Wildcard — upper bounded (like extends in TS)
public static double sum(List<? extends Number> list) {
    return list.stream().mapToDouble(Number::doubleValue).sum();
}

Comparing to TypeScript

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

TS
TypeScript (What you know)
function identity<T>(value: T): T {
  return value;
}

interface Box<T> {
  value: T;
  map<U>(fn: (v: T) => U): Box<U>;
}

// Conditional type — TS-only feature
type Unwrap<T> = T extends Promise<infer U> ? U : T;
Mirror Card
TS
From TypeScript:

You may be used to different syntax or behavior.

JV
In Java:

Java generics use type erasure — T becomes Object at runtime

Mirror Card
TS
From TypeScript:

You may be used to different syntax or behavior.

JV
In Java:

Wildcards <? extends T> and <? super T> replace TS conditional types for bounds

Mirror Card
TS
From TypeScript:

You may be used to different syntax or behavior.

JV
In Java:

No conditional types or mapped types in Java — these are TS-only

Mirror Card
TS
From TypeScript:

You may be used to different syntax or behavior.

JV
In Java:

<T extends Comparable<T>> is Java's equivalent of TypeScript's T extends SomeType

Step-by-Step Breakdown

1. Type Erasure

Java erases generic type parameters at runtime. List<String> and List<Integer> are both just List at runtime. You cannot do instanceof List<String>.

TS
TypeScript
// TS keeps generic info through type system
function isStringArray(arr: unknown[]): arr is string[] {
  return arr.every(x => typeof x === "string");
}
JV
Java
// Java — cannot check generic type at runtime
List<String> list = new ArrayList<>();
// list instanceof List<String> — ILLEGAL
Common Pitfall
Cannot create generic arrays: new T[10] is illegal in Java. Use List<T> instead.

2. Bounded Wildcards vs extends

Java wildcards ? extends T (covariant) and ? super T (contravariant) handle scenarios TypeScript handles with conditional types and covariance.

TS
TypeScript
function process<T extends Animal>(items: T[]): void {}
JV
Java
public static void process(List<? extends Animal> items) {}

3. Function<T, R> as a Type

Java uses functional interfaces like Function<T,R>, Supplier<T>, Consumer<T> where TypeScript uses inline function types.

TS
TypeScript
function transform<T, U>(fn: (v: T) => U, value: T): U {}
JV
Java
public static <T, U> U transform(Function<T, U> fn, T value) {
    return fn.apply(value);
}

4. No Conditional or Mapped Types

TypeScript's advanced type features (conditional types, mapped types, infer) have no Java equivalent. Java generics are more limited by design.

TS
TypeScript
type NonNullable<T> = T extends null | undefined ? never : T;
JV
Java
// No equivalent in Java — handle at runtime with Objects.requireNonNull()
Objects.requireNonNull(value, "value must not be null");
Rule of Thumb
When TS conditional types feel necessary in Java, consider runtime validation or design patterns instead.

Common Mistakes

When coming from TypeScript, developers often make these mistakes:

  • Java generics use type erasure — T becomes Object at runtime
  • Wildcards <? extends T> and <? super T> replace TS conditional types for bounds
  • No conditional types or mapped types in Java — these are TS-only
Common Pitfall
Don't assume Java works exactly like TypeScript. While the concepts may be similar, the syntax and behavior can differ significantly.

Key Takeaways

  • Java generics use type erasure — no runtime type info for generic parameters
  • Wildcards <? extends T> and <? super T> handle variance
  • Functional interfaces replace TS inline function types
  • Advanced TS type-level features (conditional types, infer) have no Java equivalent
Rule of Thumb
The best way to learn is by doing. Try rewriting some of your TypeScript code in Java to practice these concepts.
PreviousNext