Extending Interfaces
Overview
TypeScript is described by Microsoft as a superset of JavaScript. Every valid JavaScript code is likewise a valid TypeScript code. TypeScript can accomplish more than its predecessor, but it cannot do less. Otherwise, project migration would be far more complex, and developer acceptance would be significantly lower.
Introduction
The contract in your application is defined by the interface, which is a structure. It specifies the syntax that classes must use. An interface's structure must be followed by classes that are derived from it.
The primary advantage of TypeScript over plain JavaScript is that it enhances JavaScript's capabilities by providing functionality that assures the type safety of our program's objects. This is accomplished by inspecting the form of the values that objects take on.
Duck typing or Structural typing is the process of checking the shape. In TypeScript, interfaces are one approach to fill the job of naming data types. It's quite handy for defining contracts in TypeScript programs. We'll pick up where we left off in the previous post and look at some more TypeScript interface attributes.
The interface is not converted to JavaScript by the TypeScript compiler. The interface is used for type verification. Duck typing and structural subtyping are other terms for this process. A function or arrow function can be used to declare methods and attributes in an interface, which is specified by the keyword interface.
Interfaces, like classes, can extend each other in TypeScript. This allows us to duplicate the members of one interface to another, providing us with greater flexibility in how we utilize our interfaces. We may reuse similar implementations in multiple locations and enhance them in various ways without having to duplicate code for interfaces.
One of the main characteristics of TypeScript is Extending interfaces, which provide developers the freedom to flexibly and expressively enforce constraints on their code to lower defects and increase readability. Let's explore the many attributes of Extending interfaces and how we might use them more effectively in our projects.
Syntax:
The student interface in the definite has two properties: Id and Name. Additionally, it has a method declaration called Result that uses an arrow function and has a single number parameter and a single number return type. A typical function is used to declare the ParentName method. Any object of type student must, therefore, declare the two attributes and the two methods.
Interfaces in Typescript
JavaScript provides a significant degree of freedom to developers. At run-time, a variable started as an integer can be allocated a function literal. Variable types are unpredictable in JavaScript. As seen in the following example, an is initialized as an integer and then given a function literal:
In Typescript, there are two ways to express the structure of an object: interfaces and types (or type aliases). If you're familiar with any of the OOP languages (Java, C++, C#...), you've probably heard of/used interfaces. An interface in these languages often acts as a template for any class implementations. It makes no difference if you've never seen or used Interfaces before, or if you're unfamiliar with any of the aforementioned languages.
To keep things simple, we'll suppose that an object's structure is defined by both types and interfaces. This item may now be anything. It might be data you anticipate receiving as a response from an API.
One of the fundamental tenets of TypeScript is that values' shapes are the primary focus of type verification. It's also known as ‘structural subtyping’ or ‘duck typing.’ Interfaces serve the purpose of designating these kinds in TypeScript and are a potent tool for building contracts between your code and code from other projects.
As previously mentioned, interfaces also let you perform a process known as declaration merging and let you specify an object's shape using a different syntax. Interfaces have a little lengthier syntax but can perform any type-level operations.
A little backstory beforehand. Developers can give a type of name through interfaces for subsequent use in their applications. For instance, the administration software of a public library may provide a Book interface for information corresponding to books in the library's collection:
With it, we can make sure that the program's book data includes the vital FirstName, LastName, and Id information. The TypeScript compiler will give an error if it doesn't:
All of the characteristics in the aforementioned Student interface sample are designated as necessary. We can build an interface to anticipate a few optional attributes, though. The attribute definition can be amended to reflect this by including the ? Symbol.
To illustrate this, let's give our Book interface an optional Number attribute called Result:
Optional Characteristics
We will frequently find ourselves working on attributes that were previously set up for us, causing us to implement all of our objects inherited from the interface with the same properties set.
If we want some objects to have some but not all properties, the best way is to declare these properties as optional by simply including a question mark to the property name. For example, if we don't always require the age attribute or if it can be undefined, we must use a question mark.
An example code for defining optional properties in TypeScript Interface is shown below.
It is critical that you remember to use the question mark exactly after the property name, rather than after the colon. This indicates that the question mark should occur before the colon, and we won't get an error because we stated that age isn't required.
Extending Interfaces in TypeScript
Typescript is a programming language that can handle many sorts of values. It can provide a data type for JavaScript to convert into a strongly typed programming language, which JavaScript can not handle since it contains an extended type that can be used to extend a type into a typescript using the 'extend' keyword. This can be extended with both the class by implementing extending the interfaces by classes as well as the interfaces in which interfaces may expand with each other in the same way that classes can, and we can also state that it is flexible in utilizing the interfaces by executing in different locations.
Declaration Merging
As mentioned before, extending interfaces can be reopened to include additional characteristics and broaden the type definition. Here is a ridiculous illustration of this ability:
It's unlikely that the same interface would be reopened in such close proximity, of course. To define it in a single sentence would make it more understandable:
So, under what circumstances would you wish to expand an interface across several components of your program? Let's examine a practical use case.
Declaration Merging to Wrangle Disparate User Preferences
Consider a scenario in which you are creating a React application and you want certain pages that will let the user customize things like their profile, notification preferences, and accessibility settings.
You've divided these three issues into three distinct pages for the sake of clarity and user experience, and the source code can be found in three files: Details.tsx, Notifications.tsx, and Accessibility.tsx.
A single object that adheres to an interface we'll call Student would be great from the standpoint of application design since it would include all of the user's choices. With just one or two endpoints rather than several, you can quickly load and save the preferences object using your backend API.
Where should the Student interface be defined is the next query. You could create the interface in a separate file called student.ts and import it into the three pages, or you could use declaration merging to have each page only describe the aspects of Student that are relevant to it. For example:
The Student interface will ultimately be resolved to completely contain all the desired properties:
The software is now simpler to understand and maintain since the UI code is now contained beside just the Student attributes it controls. Nice!
Extending Interfaces in TypeScript
Mixing one or more of these into a new interface is another technique in TypeScript to extend interfaces:
Explanation
Object-oriented programmers may recognize this as familiar. However, extending interfaces provides multiple inheritances, a crucial feature that is uncommon in conventional object-oriented programming.
Extending One Interface
Multiple Extending Interfaces in TypeScript
We may combine the actions and attributes of many extending interfaces into a single interface by using multiple inheritances.
Extending multiple interfaces is a compositional idea where an interface is created to expand the properties interface requires. It varies from the idea of inheritance in object-oriented programming (OOP), where an object is a child of a specified class and compelled to extend the parent's attributes.
Extending Interfaces to Form a Type-Safe Global State Store
Consider creating a tool that allows users to manage both their daily schedules and to-do lists in one location. For keeping track of each of those activities, you'll have a few distinct UI elements:
Extending Types
Type extensions allow us to add, delete, or replace fields on existing types without requiring access to the types themselves. They also enable for better organization of our types as a result of their features. We may, for example, create classes that encapsulate a portion of our domain and provide these features to our Query type.
Type extensions are very handy when we want to edit third-party types, such as those that sit in a different assembly and are therefore inaccessible to us directly.
The & operator may be used to extend types in TypeScript. This is known as intersecting kinds, and they may be used to combine two or more separate types.
Both fields from the previous two categories will now be present in the Vehicle type. This allows you to combine as many kinds as you need. This approach is also applicable to interfaces; however, if you wish to specify your type as an interface, you must use the extends keyword.
When extending multiple interfaces, use a comma to divide them rather than the & operator. You may also use the extends keyword to extend types rather than simply interfaces, or you can mix the two. However, in order to maintain consistency, it is best to stick to one or the other.
The 'extends' keyword has been used to extend the types in typescript and also for creating the UserActivity interfaces that can extend the event type.
TypeScript extends type is described as the typescript interfaces that can extend classes, which indicates that the interfaces can start taking over the members of a class but with no implementation in which the class acts as an interface that can have all of the members which can be communicated without execution. The UserId field from the UserActivity is a string that may be added. We can also grab the remainder from the event.
Type Aliases in TypeScript
Type aliases in TypeScript generate type definitions that may be reused throughout the code. This is in contrast to type unions and intersections, where explicit type information is utilized repeatedly.
Syntax
The type keyword and a name are required for type aliases. There are two ways to make them.
- They can be defined as an object that describes the members and their kinds.
- They may also refer to other well-known kinds, such as a union type.
When the name is used again later, TypeScript will presume it refers to the aliased value. In terms of syntax and functionality, type aliases are comparable to interfaces. However, an interface can have members added later, but type aliases cannot be modified after they are declared.
Type Aliases
A type alias is just another name for any type. Not just primitives, but also object types, union types, tuples, and intersections, can be represented using type aliases. Consider the following examples:
The type keyword comes before type aliases when they are stated. Consider them to be standard JavaScript variables that represent specific values. A variable name is evaluated to the value that it represents everywhere it is used. Type aliases function similarly. When you annotate a type with its alias, the alias will evaluate to the type(s) for which it stands. You cannot declare the same type alias more than once, much like variables. TypeScript does not infer aliases; you must explicitly annotate them.
Create Type Alias
The type keyword is required to construct a type alias.
In the above code, we defined a type alias called gender. The gender type might be one of two values: 'male' or 'female'.
A compilation issue occurs when we attempt to assign a value other than the set value. This is demonstrated in the code widget below:
Conclusion
- TypeScript Interface allows us to declare the attributes that we want the entities in our project to have, including their types.
- In TypeScript, there are several alternative methods to extend object-like types using interfaces. Type aliases are another option occasionally.
- We conclude that classes have been extended into interfaces using the 'extend' keyword. We have also explored how typescript's extend type, which extends interface types, works.
- An interface can be used to expand one or more existing interfaces.
- An interface can also extend a class. If a class has private or protected members, the interface can only be implemented by that class or its subclasses.
- You may use commas to divide up several interfaces rather than the & operator when extending them. Using the extends keyword, you may extend types as well as interfaces, or you can even mix the two.
- The 'extend' keyword was used to convert classes into interfaces; we also reviewed how the typescript extend type works, how typescript extends interface types, and examples of the typescript extend type.
- Type aliases and interfaces can both be used to specify the form of an object or the signature of a function. However, the syntax is different.
- Declaration merging is only supported for interfaces, not type aliases.
- The interface keyword cannot be used to declare a union, intersection, or tuple. You may, however, utilize them within an interface.
- Type aliases and interfaces can be implemented by classes, but not type aliases that represent a union type.