Loading...

TypeScript type vs interface – What is the difference?

TypeScript type vs interface – What is the difference?

TypeScript, a superset of JavaScript, introduces powerful static typing capabilities to the dynamic world of JavaScript. A core part of TypeScript's typing system revolves around two primary constructs: type and interface. Both offer ways to define and enforce shapes of objects, but each has its unique capabilities, use cases, and limitations. Let's dive deep into understanding them.

Understanding 'Type' in TypeScript

TypeScript's type provides a way to define and give a name to specific shapes of data, be it primitive types, union types, intersection types, and more. It's a fundamental aspect of the TypeScript type system, which allows developers to create more robust and error-free code.

Definition and Basic Syntax

To declare a type, one uses the type keyword followed by the name of the type and its definition:

type Age = number; type FullName = string;

Features of 'Type'

TypeScript's type has various unique features that cater to a myriad of use cases.

Union Types

Union types allow us to represent values that can be of multiple types:

type StringOrNumber = string | number;

With this type, a variable can either be a string or a number.

Intersection Types

Intersection types are a way of combining multiple types:

type NameAndAge = { name: string } & { age: number };

Tuple Types

Tuple types represent arrays where the type of a fixed number of elements is known:

type UserTuple = [string, number]; // [name, age]

Mapped Types and Conditional Types

Mapped types help to create new types based on existing ones:

type Readonly<T> = { readonly [P in keyof T]: T[P] };

Conditional types allow types to be chosen based on conditions:

type IsString<T> = T extends string ? true : false;

Limitations and Use Cases

While type is powerful, it has its limitations. For example, you cannot define method implementations inside a type or declare the same type multiple times. type is ideal for union and intersection types, tuples, and when you need to create derived types.

Understanding 'Interface' in TypeScript

Interfaces in TypeScript serve as a powerful way to define contracts for your code and ensure adherence to specific shapes or forms of data. They primarily define the shape of object literals, classes, and function types.

Definition and Basic Syntax

Declaring an interface is done using the interface keyword:

interface User { name: string; age: number; }

Features of 'Interface'

Interfaces offer a range of unique capabilities different from types.

Extending Interfaces

Interfaces can extend other interfaces, creating a chain of inherited properties:

interface Employee extends User { employeeId: number; }

Implementing Interfaces in Classes

Classes in TypeScript can implement interfaces, ensuring they adhere to the shape defined by the interface:

class MyUser implements User { name: string; age: number; constructor(name: string, age: number) { this.name = name; this.age = age; } }

In summary, both type and interface offer unique tools to shape and enforce data structures in TypeScript. Their appropriate usage can lead to clearer, safer, and more maintainable code. For an in-depth exploration of these constructs, the official TypeScript documentation is an invaluable resource.

Optional Properties in Interfaces

In TypeScript, interfaces allow you to define the shape of an object. At times, not all properties of an interface might be required. This is where optional properties come into play. They are marked with a ? at the end of the property name:

interface Profile { firstName: string; lastName?: string; }

In the above Profile interface, firstName is a required property, while lastName is optional.

Readonly Properties

TypeScript provides a readonly modifier for properties to make sure they are not modified after creation. When a property is marked as readonly, it can only be initialized once and cannot be reassigned later.

interface Point { readonly x: number; readonly y: number; }

With this Point interface, once a point object is created, its x and y values cannot be changed.

Index Signatures

There are situations where you might not know the keys of an object ahead of time. Index signatures come to the rescue:

interface StringArray { [index: number]: string; }

Here, the StringArray interface describes arrays where the index is a number, and the value is a string.

Method Signatures in Interfaces

Interfaces can also define methods:

interface Greet { greet(name: string): string; }

This Greet interface expects an implementing object to have a greet method that takes a string argument and returns a string.

Extending Classes with Interfaces

Interestingly, interfaces can extend classes. When an interface extends a class, it inherits the members of the class but not their implementations.

class Control { private state: any; } interface SelectableControl extends Control { select(): void; }

Any class that implements SelectableControl must have a select method and also be a subclass of Control.

Advantages and Limitations

Advantages:

  • Interfaces are great for declaring the shapes of objects or classes.
  • They support declaration merging, where multiple interface declarations with the same name get automatically merged.

Limitations:

  • They can't represent union or tuple types.
  • Interface declarations only exist at compile-time and have zero runtime JS impact.

Comparing 'Type' and 'Interface'

TypeScript offers two primary ways to define shapes: type and interface.

Similarities

  • Both type and interface can be used to describe the shape of an object or function.
  • Both support intersection and union (though differently).

Differences

Syntax and Declaration

type has a more flexible syntax and can represent a wider range of shapes, including primitives, union, and tuple types:

type Name = string | string[];

On the other hand, interfaces are restricted to representing object shapes:

interface Person { name: string; }

Extensibility

Interfaces are more extensible. Multiple interfaces with the same name are automatically merged:

interface Box { height: number; } interface Box { width: number; }

For type, you'd use intersection:

type Box = Height & Width;

Class Implementation

Classes can implement interfaces using the implements keyword:

class User implements Person { name: string; }

However, classes cannot implement type.

Other Notable Differences

  • type can represent primitives like string, number, etc., while interfaces cannot.
  • type aliases are not extensible after being created.

Performance Considerations

Both type and interface are TypeScript constructs and don't exist at runtime. However, interfaces are slightly more performant at compile time, especially when reused multiple times.

Best Practices and Recommendations

When to use 'Type'

  • When you need union, tuple, or other complex types.
  • When you need type transformations, e.g., Partial<T> or Readonly<T>.

When to use 'Interface'

  • For declaring object shapes, especially for objects like function types or classes.
  • When you need declaration merging.

Combining type and interface

Both can be used in harmony, such as using type for utility operations and interface for object shapes.

Real-world Examples and Use Cases

  • Using interface to define data models in an API client.
  • Utilizing type for configuration settings that can have multiple valid forms.

Conclusion

Both type and interface are powerful tools in the TypeScript toolbox. Depending on the use-case and requirements, one might be preferable over the other.

Additional Resources

For more insights and deeper understanding, refer to the official TypeScript documentation. It provides a wealth of information, examples, and guides on these topics.

Sharing is caring

Did you like what Rishabh Rao wrote? Thank them for their work by sharing it on social media.

0/10000

No comments so far

Curious about this topic? Continue your journey with these coding courses: