Lesson 45 of 60 – Generic Interfaces
75%

Generic Interfaces in TypeScript

Generic interfaces allow you to create reusable interfaces that can work with different data types. Instead of creating separate interfaces for every type of data, you can create one generic interface and provide the required type when using it.

Note: Generic interfaces are useful for reusable data structures, API responses, collections, forms, and React or React Native applications.

1. What is a Generic Interface?

A generic interface is an interface that uses a type parameter.

interface Box<T> {
    value: T;
}

Here, T represents the type of the value property.

2. Why Use Generic Interfaces?

Generic interfaces allow one interface to work with many different data types.

interface Box<T> {
    value: T;
}

const numberBox: Box<number> = {
    value: 100
};

const stringBox: Box<string> = {
    value: "Hello"
};

The same interface works with both numbers and strings.

3. Generic Interface Syntax

A generic interface is created by placing the type parameter after the interface name.

interface Container<T> {

    value: T;

}

The type parameter can later be replaced with a specific type.

4. Generic Interface with String

interface Box<T> {
    value: T;
}

const box: Box<string> = {
    value: "TypeScript"
};

console.log(box.value);

Here, T becomes string.

5. Generic Interface with Number

interface Box<T> {
    value: T;
}

const box: Box<number> = {
    value: 500
};

console.log(box.value);

In this example, T becomes number.

6. Generic Interface with Boolean

interface Box<T> {
    value: T;
}

const box: Box<boolean> = {
    value: true
};

console.log(box.value);

Generic interfaces can also work with boolean values.

7. Generic Interface with Array

interface List<T> {
    items: T[];
}

const numbers: List<number> = {
    items: [10, 20, 30]
};

const names: List<string> = {
    items: ["Amit", "Rahul"]
};

The same interface can represent lists of different types.

8. Generic Interface for Student Data

interface Student<T> {
    id: number;
    name: string;
    data: T;
}

const student: Student<string> = {

    id: 101,
    name: "Amit",
    data: "TypeScript"

};

The data property can be customized through the generic type.

9. Student Interface with Number Data

interface Student<T> {
    id: number;
    name: string;
    data: T;
}

const student: Student<number> = {

    id: 101,
    name: "Amit",
    data: 95

};

The same student interface can store a number as its generic data.

10. Multiple Generic Parameters

An interface can contain more than one generic type parameter.

interface Pair<T, U> {
    first: T;
    second: U;
}

const pair: Pair<string, number> = {

    first: "Amit",
    second: 25

};

Here, T and U can represent different types.

11. Generic Interface with Function

A generic interface can define a function that works with a generic type.

interface Processor<T> {

    process(value: T): T;

}

const processor: Processor<string> = {

    process(value) {
        return value.toUpperCase();
    }

};

console.log(
    processor.process("hello")
);

12. Generic Interface for API Response

Generic interfaces are commonly used to describe API responses.

interface ApiResponse<T> {

    data: T;
    success: boolean;
    message: string;

}

The data property can contain different types.

13. API Response with String

interface ApiResponse<T> {

    data: T;
    success: boolean;
    message: string;

}

const response:
    ApiResponse<string> = {

    data: "Login successful",
    success: true,
    message: "Success"

};

14. API Response with Student

interface Student {
    id: number;
    name: string;
}

interface ApiResponse<T> {

    data: T;
    success: boolean;

}

const response:
    ApiResponse<Student> = {

    data: {
        id: 101,
        name: "Amit"
    },

    success: true

};

console.log(
    response.data.name
);

15. API Response with Student Array

interface Student {
    id: number;
    name: string;
}

interface ApiResponse<T> {

    data: T;
    success: boolean;

}

const response:
    ApiResponse<Student[]> = {

    data: [
        {
            id: 101,
            name: "Amit"
        },
        {
            id: 102,
            name: "Rahul"
        }
    ],

    success: true

};

console.log(
    response.data
);

16. Generic Interface with Optional Property

interface Response<T> {

    data: T;
    loading: boolean;
    error?: string;

}

const response:
    Response<string> = {

    data: "Hello",
    loading: false

};

Generic interfaces can contain optional properties just like normal interfaces.

17. Generic Interface with Readonly Property

interface Data<T> {

    readonly id: number;
    value: T;

}

const data: Data<string> = {

    id: 101,
    value: "Hello"

};

data.value = "TypeScript";

The id property cannot be reassigned after the object is created.

18. Generic Interface with Nested Data

interface ApiResponse<T> {

    data: {
        result: T;
    };

    success: boolean;

}

const response:
    ApiResponse<number> = {

    data: {
        result: 95
    },

    success: true

};

19. Generic Interface with Function Return Type

interface Factory<T> {

    create(): T;

}

const studentFactory:
    Factory<string> = {

    create() {
        return "Amit";
    }

};

console.log(
    studentFactory.create()
);

20. Generic Interface with Callback

interface Handler<T> {

    handle(
        value: T
    ): void;

}

const stringHandler:
    Handler<string> = {

    handle(value) {
        console.log(
            value.toUpperCase()
        );
    }

};

stringHandler.handle(
    "hello"
);

21. Generic Interface with Class

interface Storage<T> {

    save(value: T): void;
    get(): T;

}

class StringStorage
    implements Storage<string> {

    private value: string = "";

    save(value: string): void {

        this.value = value;

    }

    get(): string {

        return this.value;

    }

}

const storage =
    new StringStorage();

storage.save("Hello");

console.log(
    storage.get()
);

22. Generic Interface with Constraints

Generic interfaces can also use constraints.

interface Entity {
    id: number;
}

interface Repository<
    T extends Entity
> {

    getById(id: number): T;

}

interface Student extends Entity {
    name: string;
}

const repository:
    Repository<Student> = {

    getById(id) {

        return {
            id: id,
            name: "Amit"
        };

    }

};

23. Generic Interface for Form Data

interface FormState<T> {

    values: T;
    errors: string[];
    submitted: boolean;

}

interface LoginForm {

    username: string;
    password: string;

}

const form:
    FormState<LoginForm> = {

    values: {
        username: "admin",
        password: "12345"
    },

    errors: [],

    submitted: false

};

This pattern is useful when managing forms with different data structures.

24. Generic Interface in React

Generic interfaces can be used to type reusable React component props.

interface ListProps<T> {

    items: T[];

    renderItem:
        (item: T) => string;

}

function List<T>(
    props: ListProps<T>
) {

    return (
        <div>
            {props.items.map(
                props.renderItem
            )}
        </div>
    );

}

25. Generic Interface in React Native

Generic interfaces are useful for reusable React Native components that can display different types of data.

interface ListProps<T> {

    items: T[];

    getTitle:
        (item: T) => string;

}

function UserList<T>(
    props: ListProps<T>
) {

    return (
        <View>
            {props.items.map(
                (item, index) => (
                    <Text key={index}>
                        {props.getTitle(item)}
                    </Text>
                )
            )}
        </View>
    );

}

26. Generic Interface with Default Type

A generic interface can have a default type parameter.

interface Response<
    T = string
> {

    data: T;
    success: boolean;

}

const response:
    Response = {

    data: "Hello",
    success: true

};

const numberResponse:
    Response<number> = {

    data: 100,
    success: true

};

27. Generic Interface for Pagination

Generic interfaces are useful for pagination because the returned data can have different types.

interface PaginatedResponse<T> {

    data: T[];
    page: number;
    totalPages: number;

}

interface Student {

    id: number;
    name: string;

}

const response:
    PaginatedResponse<Student> = {

    data: [
        {
            id: 101,
            name: "Amit"
        }
    ],

    page: 1,
    totalPages: 5

};

28. Common Generic Interface Mistakes

  • Using any instead of a useful generic type.
  • Creating unnecessary generic parameters.
  • Using the wrong type when implementing an interface.
  • Forgetting required interface properties.
  • Using constraints incorrectly.
  • Making a simple interface unnecessarily complicated.

29. Complete Practical Example

interface Student {

    id: number;
    name: string;
    course: string;

}

interface ApiResponse<T> {

    data: T;
    success: boolean;
    message: string;

}

const response:
    ApiResponse<Student> = {

    data: {

        id: 101,
        name: "Amit",
        course: "React Native"

    },

    success: true,

    message: "Student loaded successfully"

};

console.log(
    "Student ID:",
    response.data.id
);

console.log(
    "Name:",
    response.data.name
);

console.log(
    "Course:",
    response.data.course
);

console.log(
    "Success:",
    response.success
);

This example demonstrates how a generic interface can describe a reusable API response containing student data.

30. Generic Interfaces Summary

Generic interfaces allow one interface to work with different data types while preserving TypeScript's type safety.

interface ApiResponse<T> {

    data: T;
    success: boolean;

}

const response:
    ApiResponse<string> = {

    data: "Hello",
    success: true

};

const numberResponse:
    ApiResponse<number> = {

    data: 100,
    success: true

};

Generic interfaces are especially useful for APIs, reusable components, forms, collections, repositories, and React Native applications.

📌 Key Points

  • Generic interfaces can work with different data types.
  • Generic type parameters are commonly written as T.
  • The same interface can be reused with strings, numbers, objects, and arrays.
  • Generic interfaces can have multiple type parameters.
  • Generic interfaces can define functions and callbacks.
  • Generic interfaces are useful for API responses.
  • Generic interfaces can contain optional properties.
  • Generic interfaces can contain readonly properties.
  • Generic interfaces can use constraints.
  • Generic interfaces can be implemented by classes.
  • Generic interfaces are useful for form state and pagination.
  • Generic interfaces can be used with React components.
  • Generic interfaces are useful for reusable React Native components.
  • Generic interfaces help maintain type safety in large applications.

🧠 Quick Quiz

Question: Which syntax is used to create a generic interface?