TypeScript Real Fragrance Series — Интерфейсы

JavaScript TypeScript
TypeScript Real Fragrance Series — Интерфейсы

В чем преимущества интерфейса

Преимущество первое — раньше мы писали JavaScript

Определите функцию в JavaScript для получения строки имени и возраста пользователя:

const getUserInfo = function(user) { 
    return name: ${user.name}, age: ${user.age} 
}

вызов функции:

getUserInfo({name: "koala", age: 18})

Это было совершенно нормально, когда мы раньше писали JavaScript, но если этоgetUserInfoВо время многопользовательской разработки, если это公共函数, вызовут несколько разработчиков, если не все нажмут, чтобы увидеть соответствующую функцию注释, могут возникнуть следующие проблемы:

// 错误的调用
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

JavaScript этослабо типизированныйязык, поэтому код, который мы передаем, не обнаруживается,Некоторые ошибки вы даже не можете сказать себе, но что-то пошло не так.

интерфейс в TypeScript может решить эту проблему

const getUserInfo = (user: {name: string, age: number}): string => {
  return `name: ${user.name} age: ${user.age}`;
};

Правильный вызов выглядит следующим образом:

getUserInfo({name: "kaola", age: 18});

Если звонящий делает плохой вызов, тоTypeScriptСообщение об ошибке будет дано напрямую:

// 错误的调用
getUserInfo(); // 错误信息:An argument for 'user' was not provided.
getUserInfo({name: "coderwhy"}); // 错误信息:Property 'age' is missing in type '{ name: string; }'
getUserInfo({name: "coderwhy", height: 1.88}); // 错误信息:类型不匹配

В это время вы обнаружите, что этот код все еще немного длинный, и код неудобен для чтения, что отражено в настоящее время.interfaceнеобходимость.

Рефакторинг типа пользователя, использующего интерфейс.

Сначала мы определяемIUserинтерфейс:

// 先定义一个接口
interface IUser {
  name: string;
  age: number;
}

Далее мы смотрим на函数Как писать:

const getUserInfo = (user: IUser): string => {
  return `name: ${user.name}, age: ${user.age}`;
};

// 正确的调用
getUserInfo({name: "koala", age: 18});

// Неправильный вызов такой же, как и раньше, и сообщение об ошибке такое же и не будет объяснено.

Определение функции в интерфейсе снова реформировано

Определите два интерфейса:

type IUserInfoFunc = (user: IUser) => string;

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

Затем мы можем определить функцию и вызвать функцию:

const getUserInfo: IUserInfoFunc = (user) => {
  return `name: ${user.name}, age: ${user.age}`;
};

// правильный вызов

getUserInfo({name: "koala", age: 18});

// неверный вызов

getUserInfo();

Преимущества ДВА. В прошлом мы использовали Node.js для написания серверных интерфейсов.

По сути, это описание похоже на приведенное выше, я упомяну его еще раз, просто чтобы доказать, что TypeScript действительно вкусный! Чтобы написать внутренний интерфейс, я хочу инкапсулировать класс инструмента специально для обнаружения параметров, переданных мне внешним интерфейсом, например, на рисунке ниже.validateФункции, предназначенные для параметров тестированияНо с TypeScript эту функцию проверки параметров можно опустить, мы можем написать ее так:

 const goodParams: IGoodsBody = this.ctx.body;

а такжеGoodsBodyопределяется соответствующим параметромinterface, так

// -- 查询列表时候使用的接口
interface IQuery {
    page: number;
    rows: number;
    disabledPage?: boolean; // 是否禁用分页,true将会忽略`page`和`rows`参数
 }
// - 商品
export interface IGoodsQuery extends Query {
    isOnline?: string | number; // 是否出售中的商品
    goodsNo?: string; // 商品编号
    goodsName?: string; // 商品名称
 }

Хорошо, после разговора о его нескольких преимуществах, давайте начнем изучать интерфейс! Есть много преимуществ!

Об авторе: koala, сосредоточив внимание на совместном использовании полного стека технологий Node.js, от JavaScript до Node.js, до серверной базы данных, я желаю вам стать отличным старшим инженером Node.js. [Руководство по развитию программиста] Автор, блог Github с открытым исходным кодомGitHub.com/koala-co Nth…

Основы интерфейсов

Определение интерфейса

Подобно языку java, интерфейсы определяются в TypeScript с помощью ключевого слова interface:

interface IQuery {
  page: number;
}

Вы обнаружите, что я добавилI, это личная привычка, с другой стороны, я писал java-код раньшеtslintЗапросите, иначе будет выдано предупреждение, добавлять ли лиц.

метод в интерфейсе

Глядя на интерфейс выше, мы определяемpageДля общих свойств при определении интерфейса могут быть не только свойства, но и методы, см. следующий пример:

interface IQuery {
  page: number;
  findOne(): void;
  findAll(): void;
}

Если у нас есть объект этого типа интерфейса, он должен содержать соответствующие свойства и методы (без необязательных свойств):

const q: IQuery = {
  page: 1,
  findOne() {
    console.log("findOne");
  },
  findAll() {
    console.log("findAll");
  },
};

Определить свойства в интерфейсе

общественная собственность

надpageЭто общее свойство, если есть объект на типе интерфейса, он должен содержать соответствующие общие атрибуты. Не конкретно сказать.

необязательный атрибут

По умолчанию переменная (объект) является соответствующим типом интерфейса, тогда эта переменная (объект) должна реализовывать все свойства и методы в интерфейсе.

Однако, чтобы сделать интерфейс более гибким во время разработки, мы можем захотеть сделать некоторые атрибуты необязательными (если вы хотите это реализовать, вы можете это реализовать, не имеет значения, если вы не хотите это реализовывать). ), вы можете использовать его в это время.可选属性(Когда я буду подробно объяснять функцию позже, я также упомяну, что в функции есть необязательные параметры):

interface IQuery {
  page: number;
  findOne(): void;
  findAll(): void;
  isOnline?: string | number; // 是否出售中的商品
  delete?(): void
}

В приведенном выше коде мы добавилиisOnlineсвойства иdeleteметоды, оба из которых являются необязательными:

Примечание. Если необязательный атрибут не задан, полученное значениеundefined;

Для необязательных методов вы должны сначала судить, а затем вызывать их, иначе будет сообщено об ошибке;

const q: IQuery = {
 page: 1,
 findOne() {
   console.log("findOne");
 },
 findAll() {
   console.log("findAll");
 },
};

console.log(p.isOnline); // undefined
p.delete(); // 不能调用可能是“未定义”的对象。

Правильный способ вызова следующий:

if (p.delete) {
  p.delete();
}

Вы можете спросить, что если это необязательный атрибут, то почему он должен быть определен?接口更加的灵活, некоторые свойства мы можем захотеть сделать необязательными, а если есть свойства, можно约束类型, что тоже имеет решающее значение.

свойство только для чтения

По умолчанию свойства, определенные в интерфейсе, доступны для чтения и записи: но есть ключевое словоreadonly, заданное значение атрибута не может быть изменено, и после принудительного изменения будет сообщено об ошибке.

interface IQuery {
  readonly page: number;
  findOne(): void;
}

Датьpageатрибут добавленreadonlyключевое слово, а затем присвоение ему значения сообщит об ошибке.

const q: IQuery = {
  page: 1,
  findOne() {
    console.log("findOne");
  },
};
q.page = 10;// Cannot assign to 'page' because it is a read-only property.

Расширенная глава интерфейса

интерфейс функционального типа

Интерфейс также можно использовать для нормализации формы функции. Интерфейс должен перечислить определение функции списка параметров и тип возвращаемого значения. Это написано следующим образом:

  • определяет функциональный интерфейс
  • Интерфейс принимает три параметра и не возвращает значения
  • Используйте функциональные выражения для определения функций этой формы
interface Func {
    // ✔️ 定于这个函数接收两个必选参数都是 number 类型,以及一个可选的字符串参数 desc,这个函数不返回任何值
    (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类型系统默认推论可以不必书写上述类型定义
    console.log(desc, x + y)
}

sum(32, 22)

ПРИМЕЧАНИЕ. Однако в вышеуказанном интерфейсе только одна функция находится только одна функция, TeampScript даст нам предложение использоватьtypeчтобы определить тип функции:

type Func = (x: number, y: number, desc?: string) => void;

Реализация интерфейса

Помимо определения некоторых类型规范, или, как и в других языках программирования, пусть类去实现某个接口, то класс должен явно владеть свойствами этого интерфейса и реализовывать его методы:

Будут предупреждения о модификаторах в следующем коде, игнорируйте их уже сейчас и подробно объясните // Определите интерфейс объекта

interface Entity {
  title: string;
  log(): void;
}

// реализуем такой интерфейс

class Post implements Entity {
  title: string;

  constructor(title: string) {
    this.title = title;
  }

  log(): void {
    console.log(this.title);
  }
}

Вопросы от некоторых друзей? Я определил интерфейс, но мне также нужно написать метод реализации интерфейса в классе, который наследует этот интерфейс.Не было бы мне удобнее написать метод реализации непосредственно в этом классе, а также сохранить необходимость определить интерфейс? Это место, где у новичков часто возникают сомнения.

Прежде чем ответить на этот вопрос, запомните сначала два слова,Технические характеристики!

Эта спецификация позволяет вам узнать, для чего она используется, когда вы смотрите на имя, и ее можно расширять и поддерживать.

  • существуетдизайн кода, интерфейс — это спецификация;

Интерфейсы обычно используются для определения какой-либо спецификации, например, протокола, которому вы должны следовать,

  • стоятьпроцедурный уголГоворят, что интерфейс определяет только те свойства и методы, которые должны быть предоставлены в классе, тем самым разделяя спецификацию и реализацию и повышая масштабируемость и удобство сопровождения системы;

Наследование интерфейсов

Как и классы, интерфейсы могут наследовать от других интерфейсов. Это эквивалентно дублированию всех элементов интерфейса. Интерфейс также использует ключевые словаextendsнаследовать.

interface Shape {     //定义接口Shape
    color: string;
}

interface Square extends Shape {  //继承接口Shape
    sideLength: number;
}

Интерфейс может одновременно наследовать от нескольких интерфейсов, реализуя слияние нескольких элементов интерфейса. использоватьзапятаяРазделите интерфейсы для наследования.

interface Shape {
    color: string;
}

interface PenStroke {
    penWidth: number;
}

interface Square extends Shape, PenStroke {
    sideLength: number;
}

Следует отметить, что хотя поддерживается наследование нескольких интерфейсов, если тип атрибута с тем же именем, определенный в унаследованном интерфейсе, отличается, онне могу скомпилироватьиз. Следующий код:

interface Shape {
    color: string;
    test: number;
}

interface PenStroke extends Shape{
    penWidth: number;
    test: string;
}

Кроме того, есть еще один момент по поводу наследования.Если есть класс, реализующий интерфейс Square, то необходимо реализовать не только методы Square, но и методы в интерфейсе, от которого наследуется Square.Для реализации интерфейса используйтеimplementsключевое слово .

Интерфейс индексируемого типа

Разница между интерфейсом и типом

тип работает, а интерфейс нет

  • type может объявлять псевдонимы базовых типов, типы объединения, кортежи и т. д.
// 基本类型别名
type Name = string

// 联合类型
interface Dog {
    wong();
}
interface Cat {
    miao();
}

type Pet = Dog | Cat

// 具体定义数组每个位置的类型
type PetList = [Dog, Pet]
  • В операторе типа вы также можете использовать typeof, чтобы получить тип экземпляра для назначения.
// 当你想获取一个变量的类型时,使用 typeof

let div = document.createElement('div');
type B = typeof div
  • введите другие непристойные операции
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> };

интерфейс работает, а шрифт нет

интерфейс может объявить объединение

interface User {
  name: string
  age: number
}

interface User {
  sex: string
}

/*
User 接口为 {
  name: string
  age: number
  sex: string 
}
*/

Кроме того, для получения дополнительной информации о типах вы можете проверить документацию:Официальная документация TypeScript

Резюме сценариев применения интерфейса

Как это использовать в проекте, я привел в начале два примера, а здесь напишу еще немного.Недавно я попробовал egg+ts, чтобы научиться. При написании теста параметра запроса или при возврате фиксированных данных вы будете использовать интерфейс, смотреть на простой код, читать вышеприведенную статью и испытать это на себе.

import User from '../model/user';
import Good from '../model/good';

// 定义基本查询类型
// -- 查询列表时候使用的接口
interface Query {
    page: number;
    rows: number;
    disabledPage?: boolean; // 是否禁用分页,true将会忽略`page`和`rows`参数
  }

// 定义基本返回类型
type GoodResult<Entity> = {
    list: Entity[];
    total: number;
    [propName: string]: any;
};

// - 商品
export interface GoodsQuery extends Query {
    isOnline?: string | number; // 是否出售中的商品
    goodsNo?: string; // 商品编号
    goodsName?: string; // 商品名称
}
export type GoodResult = QueryResult<Good>;

Суммировать

TypeScriptОн еще довольно ароматный, давайте объявим пост завтра.TypeScriptМощные псевдонимы типов. Сегодня я так много поделился. Если вас интересует общий контент, вы можете подписаться на официальную учетную запись «Руководство по развитию программиста», добавить меня в WeChat (coder_qi) и включить вас в техническую группу для долгосрочного обмена и обучения. .

Справочная статья

nuggets.capable/post/684490…

Woohoo.tea посмотри на i.com/afraid/57 рисоварка 5 ах 0...

nuggets.capable/post/684490…

Tickets.WeChat.QQ.com/Yes/A Jiao 45 Внезапно 7AZ…

Стать.Hubeiwiz.com/card/from/55not7…

Оригинальные статьи серии Node

Глубокое понимание процессов и потоков в Node.js

Если вы хотите изучить Node.js, сначала необходимо понять поток.

Когда требуется, вы действительно понимаете разницу между экспортом и модулем.экспорт?

В статье об интерпретации исходного кода подробно рассматривается модуль Events.

Node.js расширенное расширенное изучение файлового модуля fs

Подписывайтесь на меня

  • Добро пожаловать, чтобы добавить меня в WeChat (coder_qi), привлечь вас в техническую группу, долгосрочный обмен и изучение...
  • Добро пожаловать, чтобы обратить внимание на «Руководство по развитию программиста на севере», общедоступную учетную запись, которая поможет вам расти с душой...