Как использовать TypeScript в своем проекте 🤔

внешний интерфейс JavaScript TypeScript
Как использовать TypeScript в своем проекте 🤔

1. Предисловие ✍️

  • мы все знаем,JavaScriptЭто очень гибкий язык программирования, и эта гибкость делает его, с одной стороны, самым популярным языком программирования, но также приводит к неравномерному качеству кода, высоким затратам на обслуживание и множеству ошибок во время выполнения.
  • TypeScriptдобавленсистема типовизJavaScript,Подходит для любого размерас проект.TypeScriptизсистема типовво многом компенсируютJavaScriptНедостатки.
  • Система типов классифицируется по «времени проверки типа», которые можно разделить надинамический типа такжестатический тип:
    • динамический типЭто означает, что проверка типов выполняется во время выполнения.Ошибки типов в этом языке часто приводят к ошибкам выполнения.Мы знакомы сJavaScriptТо есть он относится к динамическому типу, который является интерпретируемым языком и не имеет стадии компиляции.
    • статический типЭто означает, что тип каждой переменной можно определить на этапе компиляции, а ошибки типа в этом языке часто приводят к синтаксическим ошибкам. из-заTypeScriptПеред запуском его нужно скомпилировать какJavaScript, а проверка типов выполняется на этапе компиляции, поэтомуTypeScriptпринадлежатьстатический тип.
  • Возможно, новички подумают, что использованиеTypeScriptНеобходимо написать дополнительный код, что снижает эффективность разработки. Чего они могут не знать, так это того, чтоTypeScriptРасширены функции редактора (IDE), включая завершение кода, подсказки интерфейса, переходы к определениям, рефакторинг кода и т. д., что значительно повышает эффективность разработки.TypeScriptСистема типов может повысить удобство сопровождения и уменьшить количество ошибок в крупных проектах.
  • Чтобы улучшить качество разработки, ниже будет подробно рассказано, как использовать его в проекте.TypeScript.

2. Практика в проекте

2.1 Эффективно используйте аннотации типов

  • мы можем пройти/** */Примечание формы даетTypeScriptТип подсказки разметки:

image.png

  • При наведении указателя мыши на место, где используется шрифт, в редакторе будут более подсказки:

image.png

2.2 Эффективно используйте расширение типа

  • TypeScriptСуществует два способа определения типов в интерфейсе:interface) и введите псевдонимы (type alias). В следующем примере определены те же типы, за исключением синтаксиса:

image.png

  • И интерфейсы, и псевдонимы типов могут быть расширены:

image.png

  • Интерфейсы и псевдонимы типов не исключают друг друга, то есть интерфейсы могут расширять псевдонимы типов, а псевдонимы типов также могут расширять интерфейсы:

image.png

  • TypeScript: Interfaces vs TypesРазница между интерфейсом и псевдонимом типа подробно описана в разделе и не будет здесь подробно рассматриваться.
  • Когда выбирать интерфейсы и псевдонимы типов:
    • Используется при определении общедоступного API (например, при редактировании библиотеки).interface, что позволяет пользователям удобно наследовать интерфейс;
    • При определении свойств компонента (Props) и статус (State), рекомендуется использоватьtype,потому чтоtypeболее ограничительный;
    • typeТипы нельзя редактировать дважды, в то время какinterfaceМожет быть продлен в любое время.

2.3 Эффективное использование декларационных документов

  • Файл объявления должен начинаться с.d.tsявляется суффиксом. Вообще говоря,TypeScriptбудет анализировать все элементы в проекте*.tsфайл и, следовательно, также содержит файлы, начинающиеся с.d.tsКонец файла манифеста.

image.png

  • если толькоtsconfig.jsonКонфигурация содержитtyping.d.tsфайл, потом все остальное*.tsфайл может получить определения типов в файле объявлений.

2.3.1 Документы-декларации третьих лиц

  • когда вTypeScriptПри использовании сторонней библиотеки в проекте нам необходимо обратиться к ее файлу объявлений, чтобы получить соответствующее завершение кода, подсказки интерфейса и другие функции.
  • Для большинства сторонних библиотек сообщество определило для нас свои файлы объявлений, и мы можем загрузить и использовать их напрямую. Обычно рекомендуется использовать@typesУнифицированное управление файлами объявлений сторонних библиотек,@typesСпособ использования очень прост, непосредственно используйтеnpmилиyarnУстановите соответствующий модуль объявлений. кlodashНапример:

image.png

2.3.2 Файл пользовательской декларации

  • Когда сторонняя библиотека не предоставляет файл объявления, нам нужно написать файл объявления самостоятельно. кantd-dayjs-webpack-pluginНапример, когда вconfig.tsиспользуется вantd-dayjs-webpack-plugin, если редактор не найдет его файл объявления, произойдет следующая ошибка:

image.png

  • когда мы используемyarn add @types/antd-dayjs-webpack-plugin --devПри попытке решить проблему получаю следующую ошибку:

image.png

  • То есть файл объявления, относящийся к библиотеке, не может быть найден (можно найти вздесьИщите нужный вам файл декларации, если не можете найти, значит его нет).
  • Чтобы решить сообщение об ошибке редактора, мы можем использовать другой предоставленный им метод: добавить файл, содержащийdeclare module 'antd-dayjs-webpack-plugin';новый файл декларации. Мы также можем не добавлять новые файлы, как было сказано ранее.typing.d.tsПросто добавьте следующее:

image.png

глобальная переменная

  • когда нам нужноtsфайл с использованием того жеTypeScriptтип, обычная практика будет вconstant.tsОбъявите соответствующий тип в файле и поместите егоexportвыйти к другимtsдокументimportИспользование, несомненно, приведет к созданию большого количества громоздкого кода.
  • Как упоминалось ранее, покаtsconfig.jsonКонфигурация содержит наш пользовательский файл декларации*.d.ts, определения типов в файле объявлений могут использоваться*.tsфайл получен. Таким образом, мы можем объединить несколькоtsГлобальный тип, который должен использовать файл, записан в файле объявления, и вам нужно использовать этот типtsфайл не требуетсяimportможно использовать напрямую.

Пространства имен

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

image.png

  • существуетtsИспользование файла:

image.png

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

2.4 Эффективно используйте новые функции JS, поддерживаемые TypeScript

2.4.1 Необязательная цепочка

  • Необязательная цепочка ?.даES11(ES2020)добавленные функции,TypeScript 3.7Эта функция поддерживается.дополнительная цепочкаЭто может избавить нас от необходимости выполнять избыточные различные предварительные проверки при запросе объектов с несколькими уровнями:

image.png

  • В противном случае перейдите непосредственно кuser.info.getAge()легко попастьUncaught TypeError: Cannot read property....
  • использовалдополнительная цепочка, приведенный выше код станет:

image.png

  • дополнительная цепочка— это оператор, который проверяет существование свойства перед попыткой доступа к нему.TypeScriptпытаясь получить доступuser.infoраньше попытаюсь получить доступuser, только тогда, когдаuser если не nullни одинundefinedБудет продолжать посещать вниз, еслиuserДа null или undefined, то выражение возвращает сразуundefined.
  • В настоящее время необязательная цепочка поддерживает следующие синтаксические операции:

image.png

2.4.2 Нулевой объединяющий оператор

  • Нулевой оператор объединения ??даES12(ES2021)добавленные функции,TypeScript 3.7Эта функция поддерживается. Когда операнд слеваnull или undefinedКогда , возвращает свой правый операнд, в противном случае возвращает свой левый операнд.

image.png

  • И логический оператор ИЛИ (||) разные,||будет иметь левый операнд какfalsyзначение (например,'' или 0) возвращает правый операнд. То есть, если вы используете||установить значения по умолчанию для некоторых переменных, вы можете столкнуться с неожиданным поведением:

image.png

2.5 Эффективно используйте модификаторы доступа

  • TypeScriptОпределение класса позволяет использоватьprivate,protected а также publicЭти три модификатора доступа объявляют ограничения доступа к членам и проверяются во время компиляции:
    • public: общедоступный тип, к которому можно получить доступ внутри класса, подклассов и вне класса.Если модификатор не добавлен, этот уровень доступа используется по умолчанию;
    • protected: тип защиты, доступ к которому возможен внутри класса и подкласса, но не вне класса;
    • private: закрытый тип, доступный только внутри текущего класса.
  • Если модификатор не добавлен, по умолчаниюpublicУровень доступа:

image.png

  • Приведенный выше код может получитьTypeScript Playgroundв рабочем состоянии, вJSобласти, мы можем видеть сбежавшихPersonОпределение класса с удаленными модификаторами доступа:

image.png

  • Это означает, что экранированный кодJSОн может быть правильно выполнен в среде и не будет ограничен. Но в редакторе мы видимp.nameОно помечено как ошибка, и вы можете навести указатель мыши, чтобы увидеть конкретное сообщение об ошибке.
  • TypeScriptРасширяет более строгий синтаксис и использует LSP и компиляторы, чтобы помочь разработчикам всреда разработкиКак можно раньше выявляйте и решайте существующие или существующие проблемы.
  • Однако, как показано выше, библиотека JS, скомпилированная TS, не ограничивает использование конечных пользователей. То есть, если использоватьTypeScriptНапишите библиотеку, которая используетprivate или protectedчтобы ограничить доступ к членам, в своих пользователях также используйтеTypeScriptне проблема, когда его пользователи используютJavaScript, но не ограничивается ожиданиями.

Очевидно, ECMAScript был вдохновлен TypeScript, представил новый синтаксис определения класса в ES2015 и начал думать об ограничениях доступа к членам, и предложил схему, основанную на определении закрытого члена Symbol и замыкания, Конечно, эта схема не очень приемлема для использования. После 4 лет размышлений, проектирования и обсуждения, наконец, выпустили использование в ES2019.#номер для определения спецификации закрытых членов. Chrome 74+ и Node 12+ реализовали спецификацию этого определения частного члена.

  • видно, даже еслиTypeScriptимеютprivateмодификаторы доступа,#privateFieldеще вTypeScriptимеет смысл существования.

2.6 Эффективно используйте сужение типа

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

2.6.1 Утверждение типа

  • Утверждения типа могут явно указыватьTypeScriptПодробный тип значения. Когда в некоторых случаях мы очень уверены в типе значения, даже сTypeScriptВыведенный тип несовместим, тогда мы можем использовать утверждение типа, синтаксис следующий:

image.png

  • существуетtsxграмматика(Reactизjsxграмматическийtsверсия) должен использовать первый, т.е.值 as 类型. В то же время, поскольку<>С общим синтаксисом легко конфликтовать, поэтому при использовании утверждения типа рекомендуется использовать единообразно值 as 类型такой синтаксис.
  • когдаTypeScriptКогда мы не уверены, какого типа переменная типа объединения, мыможет получить доступ только к свойствам или методам, которые являются общими для всех типов этого типа объединения.

image.png

  • Иногда нам действительно нужно получить доступ к одному из свойств или методов, специфичных для типа, когда мы не уверены в типе, например:

image.png

  • В приведенном выше примере получитеanimal.swimсообщит об ошибке, когда . На этом этапе вы можете использовать утверждения типа дляanimalутверждать какFishтип, вы можете разрешить доступanimal.swimСообщается об ошибке:

image.png

  • Следует отметить, что утверждения типа могут только «обмануть»TypeScriptкомпилятор, нельзя избежатьВремя выполненияошибка, вместо этого злоупотребляя утверждениями типаМожет вызвать ошибки времени выполнения:

image.png

  • TypeScriptКомпилятор доверяет нашему утверждению, поэтому вызываетswim()Нет ошибки компиляции, когдаCatне наswimметод приведет к ошибке во время выполнения.
  • 🏁: Будьте осторожны при использовании утверждений типа, старайтесь избегать вызова методов или ссылок на глубокие свойства после утверждений, чтобы уменьшить количество ненужных ошибок во время выполнения.

2.6.2 Типовые ограждения

  • Типовые охранники бывают в основном следующими способами:
    • typeof: используется для сужденияnumber,string,booleanилиsymbolчетыре типа;
    • instanceof: используется для определения принадлежности экземпляра к классу
    • in: используется для определения того, принадлежит ли свойство/метод объекту

typeof

  • годный к употреблениюtypeofреализует сужение типа иneverСвойства типа проверяются всесторонне, как показано в следующем коде:

image.png

  • Видно, что в концеelseВнутри ветки мы сужаем его доneverизfooприсвоить явно объявленномуneverПеременные, если все логически правильно, то это должно уметь компилироваться и проходить. Но если однажды ваш коллега изменит егоFooтип:

image.png

  • Однако он забыл изменить в то же времяcontrolFlowAnalysisWithNeverПоток управления в методе, на этот разelseразветвленныйfooТип будет сужен доbooleanтип, который не может быть присвоенneverтип, будет сгенерирована ошибка компиляции. используяneverЧтобы избежать появления вновь добавленных типов объединения без соответствующих реализаций, мы можем гарантировать, чтоcontrolFlowAnalysisWithNeverПути всегда исчерпаныFooвсех возможных типов, что гарантирует сохранность кода.

instanceof

  • использоватьinstanceofОператор сужает тип переменной:

image.png

in

  • использоватьinПроведите проверку недвижимости:

image.png

2.6.3 Двойное утверждение

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

image.png

  • Нужно знать, что любой тип может быть утвержден какany,а такжеanyМожно утверждать, что он любого типа.
  • Если мы все еще хотим использовать этот тип, мы можем использовать двойное утверждение:

image.png

  • TypeScript 3.0добавил новыйunknownтип, который является более безопаснымany копия. Все можно отметить какunknownтипа, ноunkonwnОн должен быть назначен другим типам после оценки типа и условного контроля, и никакая операция не может быть выполнена до оценки типа и условного контроля.
  • Операция двойного утверждения в нашем примере выше неразумна, просто чтобы проиллюстрировать эффект двойного утверждения.
  • 🏁:Никогда не используйте двойные утверждения без крайней необходимости.
  • Давайте рассмотрим более распространенный сценарий использования: предположим, мы находимся вTypeScriptВ проекте аJavaScriptнаписанная библиотека, которая предоставляется через отдельный файл объявленийTypeScriptподдержку, то может быть ситуация:

image.png

  • method() существует .d.tsТип параметра, объявленный вSomeType, но поскольку файл объявления не обновляется вовремя, он фактически принимает другой тип параметра, напримерnull.

image.png

  • В этом случае вы можете использоватьunknownтип для реализации входящегоnull:

image.png

  • Таким образом, проверка типов компилятора может пройти нормально.

2.7 Эффективно используйте постоянное перечисление

  • Постоянное перечисление выполняется с помощьюconst enumОпределенные типы перечисления:

image.png

  • Разница между постоянным перечислением и обычным перечислением заключается в том, что первое будетудален во время компиляции, и не может содержать вычисляемых членов (то есть инициализаторы константных членов перечисления могут содержать только литеральные значения и другие вычисляемые значения перечисления).
  • Результат компиляции приведенного выше примера:

image.png

  • Если вычисляемый элемент включен, на этапе компиляции будет сообщено об ошибке:

image.png

  • Значение обычного перечисления не вычисляется на этапе компиляции, а сохраняется до этапа выполнения программы.Давайте рассмотрим следующий пример:

image.png

  • Результат компиляции приведенного выше примера:

image.png

  • Как видите, когда нам не нужен объект, но нужно значение объекта, мы можем использовать постоянное перечисление, что позволяет избежать создания избыточного кода и косвенных ссылок во время компиляции.

2.8 Эффективно используйте расширенные типы

  • Кромеstring,number,booleanВ дополнение к этому базовому типу мы также должны понимать некоторые дополнительные способы использования в объявлениях некоторых типов.

2.8.1 Индекс типа (keyof)

  • keyofпохожий наObject.keys, используемый для получения типа объединения Key в интерфейсе:

image.png

2.8.2 Типовые ограничения (расширение)

  • TypeScriptсередина extendsКлючевые слова отличаются отClassпосле использованияextendsФункция наследования обычно используется в дженериках, и ее основная функция заключается в ограничении дженериков:

image.png

  • extendsчасто сkeyofиспользуются вместе, например, у нас естьgetValueМетод специально используется для получения значения объекта, но объект не определен, мы можем использоватьextends а также keyofСделайте ограничения:

image.png

  • Когда входящий объект не имеетkey, редактор сообщит об ошибке.

2.8.3 Типовая карта (в)

  • inФункция ключевого слова в основном заключается в отображении типов, обходе существующего интерфейса.keyИли перебирать типы союзов. со встроенным универсальным интерфейсомReadonlyНапример, это реализовано следующим образом:

image.png

  • Что он делает, так это делает все свойства интерфейса доступными только для чтения:

image.png

2.8.3 Тип условия (U ? X : Y)

  • Правила синтаксиса для условных типов такие же, как и для троичных выражений, и часто используются в случаях, когда тип неясен:

image.png

  • Вышеизложенное означает, что еслиTдаUПодмножество , является типомX, иначе типY. со встроенным универсальным интерфейсомExtractНапример, это реализовано следующим образом:

image.png

  • TypeScriptбуду использоватьneverТипы для представления состояний, которые не должны существовать. Вышеупомянутое означает, что если тип в T существует в U, вернуть его, в противном случае отбросить.
  • Предположим, у нас есть два класса с тремя публичными свойствами, которые можно передать черезExtractИзвлеките эти три общедоступных свойства:

image.png

2.8.4 Утилиты-дженерики

  • TypesScriptСуществует множество встроенных универсальных инструментов, которые были представлены ранее.Readonly,ExtractОба встроенных дженерика находятся вTypeScriptВстроенныйlib.es5.d.tsопределены в , поэтому их можно использовать напрямую без каких-либо зависимостей.

image.png

  • Поскольку исходный код может быть напрямуюlib.es5.d.tsКак видно из файла, здесь он не будет подробно останавливаться, ниже описаны функции и методы использования нескольких распространенных парадигм инструментов.
  • ExcludeРоль представленного ранееExtractНаоборот, еслиTвведитеUЕсли он не существует, вернуть, в противном случае отказаться.

image.png

  • PartialИспользуется, чтобы сделать все свойства интерфейса необязательными:

image.png

  • RequiredЭффект точно такой же, какPartialВместо этого измените все необязательные свойства в интерфейсе на обязательные:

image.png

  • PickВ основном используется для извлечения некоторых свойств интерфейса:

image.png

  • OmitРоль прямо противоположна Pick, в основном используется для удаления определенных свойств интерфейса:

image.png

3. Резюме 📝

  • TypeScriptОн очень мощный, расширяет функции редактора (IDE) и предоставляет такие возможности, как завершение кода, подсказки интерфейса, переход к определениям и рефакторинг кода.
  • TypeScriptможет иJavaScriptсосуществовать, а значитJavaScriptПроекты могут быть постепенно перенесены вTypeScript.
  • В этой статье описываетсяTypeScriptНесколько распространенных практик в проекте, надеюсь еще не трогалTypeScriptили вправоTypeScriptДрузья, кто еще не знаком с ним, спешите применить его на практике в проекте, и стремиться улучшить ремонтопригодность кода и счастье разработки 💪.

4. Справочная документация

  1. Официальная документация TypeScript
  2. Sharp ES6 — синтаксический сахар класса
  3. Элементы класса — MDN
  4. Понимание сужения типов TypeScript