What benefits do interfaces bring
Benefit One — We used to write JavaScript
JavaScript defines a function to retrieve a string of user names and ages:
const getUserInfo = function(user) {
return name: ${user.name}, age: ${user.age}
}
Copy the code
Function call:
getUserInfo({name: "koala".age: 18})
Copy the code
This is perfectly normal when we were writing JavaScript, but if this getUserInfo is in multi-developer development, if it is a public function, multiple developers will call it, and if everyone does not click on the function to see the corresponding comment, the following problems may occur:
// Wrong call
getUserInfo() // Uncaught TypeError: Cannot read property 'name' of undefined
console.log(getUserInfo({name: "kaola"})) // name: kaola, age: undefined
getUserInfo({name: "kaola".height: 1.66}) // name: koala, age: undefined
Copy the code
JavaScript is a weakly typed language, so it doesn’t do any checks on the code we pass in, and there are some errors that you can’t even explain to yourself, but there are problems.
Interfaces in TypeScript solve this problem
const getUserInfo = (user: {name: string, age: number}): string= > {
return `name: ${user.name} age: ${user.age}`;
};
Copy the code
The correct call is as follows:
getUserInfo({name: "kaola".age: 18});
Copy the code
If the caller makes an incorrect call, TypeScript will directly inform you of the error:
// Error with getUserInfo(); // Error message: An argument for 'user' was not provided. GetUserInfo ({name: "coderwhy"}); // Error: Property 'age' is missing in type '{name: string; }' getUserInfo({name: "coderwhy", height: 1.88}); // Error message: Type mismatchCopy the code
At this point, you will find that the code is still a bit long and difficult to read, which shows the necessity of interface.
Refactoring the user type using interface.
Let’s define an IUser interface:
// Define an interface
interface IUser {
name: string;
age: number;
}
Copy the code
Now let’s see how the function is written:
const getUserInfo = (user: IUser): string= > {
return `name: ${user.name}, age: ${user.age}`;
};
// Correct call
getUserInfo({name: "koala".age: 18});
Copy the code
// The error call is the same as before, and the error message is the same.
The definition of functions in interfaces has been reworked
Define two interfaces:
type IUserInfoFunc = (user: IUser) = > string;
interface IUser {
name: string;
age: number;
}
Copy the code
Then we define the function and call the function:
const getUserInfo: IUserInfoFunc = (user) = > {
return `name: ${user.name}, age: ${user.age}`;
};
Copy the code
// Correct call
getUserInfo({name: "koala".age: 18});
Copy the code
// Wrong call
getUserInfo();
Copy the code
Benefit TWO — In the past we used node.js to write back-end interfaces
This is a similar explanation, but I’ll mention it again, to prove that TypeScript really smells good! To write a back-end interface, I will specifically encapsulate a utility class that detects the parameters passed to me from the front end, as shown in the following figurevalidate
A function designed to test parametersBut with TypeScript, the argument validation function can be omitted. Instead, we can write:
const goodParams: IGoodsBody = this.ctx.body;
Copy the code
And GoodsBody is the interface that corresponds to the parameter definition, like this
// -- the interface used to query the list
interface IQuery {
page: number;
rows: number; disabledPage? :boolean; // Whether to disable paging. True will ignore the 'page' and 'rows' arguments
}
/ / - goods
export interface IGoodsQuery extendsQuery { isOnline? :string | number; // Whether the item is for salegoodsNo? :string; // Product idgoodsName? :string; // Product name
}
Copy the code
Ok, after saying a few of its benefits, let’s start to learn about interface! There are many advantages!
Koala is dedicated to sharing the complete Node.js technology stack, from JavaScript to Node.js, to back-end database. Wish you become an excellent senior Node.js engineer. [Programmer growth refers to north] Author, Github blog open source project github.com/koala-codin…
The basics of interfaces
Interface Definition
Like the Java language, TypeScript uses the interface keyword to define interfaces:
interface IQuery {
page: number;
}
Copy the code
You will notice that I always add an “I” in front of the interface, which is a personal habit. Previously, I have been writing Java code, on the other hand, TSLint requires that, otherwise, it will send a warning.
Defines methods in the interface
In the following example, we define the page general attribute. When we define the interface, we can not only have properties, but also can have methods.
interface IQuery {
page: number;
findOne(): void;
findAll(): void;
}
Copy the code
If we have an object of this interface type, then we must include the corresponding properties and methods (if no optional properties are available) :
const q: IQuery = {
page: 1.findOne() {
console.log("findOne");
},
findAll() {
console.log("findAll"); }};Copy the code
Attributes defined in the interface
Common properties
The page above is a common attribute, and if there is an object of this interface type, it must contain the corresponding common attribute. I won’t go into the details.
Optional attribute
By default, a variable (object) is the corresponding interface type, so that variable (object) must implement all properties and methods in the interface.
However, in order to make the interface more flexible, we may want to make some properties optional (if we want to implement them, it is ok not to implement them). In this case, we can use optional properties (the function has optional parameters, as we will explain later in more detail) :
interface IQuery {
page: number;
findOne(): void;
findAll(): void; isOnline? : string | number;// Whether the item is for sale
delete? () :void
}
Copy the code
In the above code, we added the isOnline attribute and the delete method, both of which are optional:
Note: If the optional attribute is not assigned, the value is undefined;
For optional methods, you must judge them first and then call them. Otherwise, an error will be reported.
const q: IQuery = {
page: 1.findOne() {
console.log("findOne");
},
findAll() {
console.log("findAll"); }};console.log(p.isOnline); // undefined
p.delete(); // Cannot call an object that may be "undefined".
Copy the code
The correct call is as follows:
if (p.delete) {
p.delete();
}
Copy the code
So you might ask if it’s optional, if it’s optional, why define it? The main reason for defining optional attributes is that, in order to make the interface more flexible, some attributes may be designed to be optional and, if there are any, to constrain the type, which is also critical.
Read-only property
By default, attributes defined in an interface are readable and writable, but there is one keyword, readonly, which cannot be modified.
interface IQuery {
readonly page: number;
findOne(): void;
}
Copy the code
Assigning the readonly keyword to the page attribute will cause an error.
const q: IQuery = {
page: 1.findOne() {
console.log("findOne"); }}; q.page =10;// Cannot assign to 'page' because it is a read-only property.
Copy the code
Advanced section of interfaces
Function type interface
Interfaces can also be used to standardize the shape of functions. The function definition that needs to list the return value type of the parameter list in Interface. It is written as follows:
- Defines a function interface
- The interface accepts three parameters and does not return any values
- Use function expressions to define functions of this shape
interface Func {
// ✔️ specifies that the function takes two mandatory arguments of type number and an optional string argument, desc. The function returns no value
(x: number, y: number, desc? : string):void
}
const sum: Func = function (x, y, desc = ' ') {
// const sum: Func = function (x: number, y: number, desc: string): void {
// Ts type system default corollaries do not need to write the above type definition
console.log(desc, x + y)
}
sum(32.22)
Copy the code
Note: However, there is only one function in the interface above, TypeScript suggests using type to define the type of a function:
type Func = (x: number, y: number, desc? : string) = > void;
Copy the code
Interface implementation
In addition to defining a type specification, an interface can also, like other programming languages, have a class implement an interface. The class must explicitly own the properties of the interface and implement its methods:
There is a warning about modifiers in the following code, which is ignored for now and explained in more detail
interface Entity {
title: string;
log(): void;
}
Copy the code
// Implement such an interface
class Post implements Entity {
title: string;
constructor(title: string) {
this.title = title;
}
log(): void {
console.log(this.title); }}Copy the code
Question from some friends? I define an interface, but I need to write the implementation method of the interface in the class that inherits the interface. Wouldn’t it be easier for me to write the implementation method directly in the class, without having to define the interface? This is where beginners often get confused.
Before you answer this question, remember two words: specification!
It’s a specification that you can look at the name, you know what it’s for, it’s extensible, it’s maintainable.
- In code design, an interface is a specification;
Interfaces are often used to define some kind of specification, like a protocol that you have to follow,
- From the point of view of program, interface only specifies the attributes and methods that must be provided in the class, thus separating specification and implementation, and enhancing the extensibility and maintainability of the system.
Inheritance of interfaces
Like classes, interfaces can inherit from other interfaces. This is equivalent to copying all the members of the interface. Interfaces are also inherited with the extends keyword.
interface Shape { // Define interface Shape
color: string;
}
interface Square extends Shape { // Inherits interface Shape
sideLength: number;
}
Copy the code
An interface can inherit multiple interfaces to merge interface members. Separate the interfaces to be inherited with commas.
interface Shape {
color: string;
}
interface PenStroke {
penWidth: number;
}
interface Square extends Shape, PenStroke {
sideLength: number;
}
Copy the code
It is important to note that although multiple interfaces can be inherited, they will not compile if the same attributes defined in the inherited interface are of different types. The following code:
interface Shape {
color: string;
test: number;
}
interface PenStroke extends Shape{
penWidth: number;
test: string;
}
Copy the code
Another point about inheritance is that if you now have a class that implements the Square interface, you need to implement not only Square’s methods, but also the methods in the interface that Square inherits, using the implements keyword.
Indexable type interface
Interface and Type
Type works and interface doesn’t
- Type can declare basic type aliases, union types, tuples, and so on
// Alias type Name = string // interface Dog {wong(); } interface Cat { miao(); =} type of Pet Dog | Cat / / specific define the type of array position of each type PetList = [Dog, Pet]Copy the code
- The type statement can also be assigned to the typeof the instance obtained using typeof
When you want to get the typeof a variable, use typeof
let div = document.createElement('div');
type B = typeof div
Copy the code
- Type Other operations
type StringOrNumber = string | number;
type Text = string | { text: string };
type NameLookup = Dictionary<string, Person>;
type Callback<T> = (data: T) = > void;
type Pair<T> = [T, T];
type Coordinates = Pair<number>;
type Tree<T> = T | { left: Tree<T>, right: Tree<T> };
Copy the code
Interface works and type doesn’t
Interface can declare merge
interface User {
name: string
age: number
}
interface User {
sex: string
}
/* User interface {name: string age: number sex: string} */
Copy the code
For more information on Type, check out the TypeScript official documentation
Summary of application scenarios of interfaces
I have already given two examples of how to use it in a project. Here I will write a little more briefly. I recently tried egg+ TS to learn more about it. When writing query parameter verification, or when returning fixed data, will use the interface, look at a simple code, have read the above article, experience it yourself.
import User from '.. /model/user';
import Good from '.. /model/good';
// Define the basic query type
// -- the interface used to query the list
interface Query {
page: number; rows: number; disabledPage? : boolean;// Whether to disable paging. True will ignore the 'page' and 'rows' arguments
}
// Define the base return type
type GoodResult<Entity> = {
list: Entity[];
total: number;
[propName: string]: any;
};
/ / - goods
export interface GoodsQuery extendsQuery { isOnline? : string | number;// Whether the item is for salegoodsNo? : string;// Product idgoodsName? : string;// Product name
}
export type GoodResult = QueryResult<Good>;
Copy the code
conclusion
TypeScript still smells good, so check out tomorrow’s post about TypeScript’s powerful type aliases. Today share so much, if you are interested in the content of the share, you can pay attention to the public account “Programmer growth refers to north”, add my wechat (coder_QI), pull you into the technical group, long-term exchange and learning.
Refer to the article
Juejin. Cn/post / 684490…
www.teakki.com/p/57dfb5a0d…
Juejin. Cn/post / 684490…
Mp.weixin.qq.com/s/aj45tr7AZ…
Cw.hubwiz.com/card/c/55b7…
Node series original articles
Learn more about processes and threads in Node.js
To learn node. js, it is necessary to know stream first
Exports: module. Exports: module
Understand the Events module thoroughly
Node.js advanced fs file module learning
Pay attention to my
- Welcome to add my wechat (COder_QI), pull you into the technology group, long-term exchange and learning…
- Welcome to “programmer growth refers to the north”, a heart to help you grow the public number…