1. Предисловие ✍️
- мы все знаем,
JavaScriptЭто очень гибкий язык программирования, и эта гибкость делает его, с одной стороны, самым популярным языком программирования, но также приводит к неравномерному качеству кода, высоким затратам на обслуживание и множеству ошибок во время выполнения. -
TypeScriptдобавленсистема типовизJavaScript,Подходит для любого размерас проект.TypeScriptизсистема типовво многом компенсируютJavaScriptНедостатки. - Система типов классифицируется по «времени проверки типа», которые можно разделить надинамический типа такжестатический тип:
-
динамический типЭто означает, что проверка типов выполняется во время выполнения.Ошибки типов в этом языке часто приводят к ошибкам выполнения.Мы знакомы с
JavaScriptТо есть он относится к динамическому типу, который является интерпретируемым языком и не имеет стадии компиляции. -
статический типЭто означает, что тип каждой переменной можно определить на этапе компиляции, а ошибки типа в этом языке часто приводят к синтаксическим ошибкам. из-за
TypeScriptПеред запуском его нужно скомпилировать какJavaScript, а проверка типов выполняется на этапе компиляции, поэтомуTypeScriptпринадлежатьстатический тип.
-
динамический типЭто означает, что проверка типов выполняется во время выполнения.Ошибки типов в этом языке часто приводят к ошибкам выполнения.Мы знакомы с
- Возможно, новички подумают, что использование
TypeScriptНеобходимо написать дополнительный код, что снижает эффективность разработки. Чего они могут не знать, так это того, чтоTypeScriptРасширены функции редактора (IDE), включая завершение кода, подсказки интерфейса, переходы к определениям, рефакторинг кода и т. д., что значительно повышает эффективность разработки.TypeScriptСистема типов может повысить удобство сопровождения и уменьшить количество ошибок в крупных проектах. - Чтобы улучшить качество разработки, ниже будет подробно рассказано, как использовать его в проекте.
TypeScript.
2. Практика в проекте
2.1 Эффективно используйте аннотации типов
- мы можем пройти
/** */Примечание формы даетTypeScriptТип подсказки разметки:
- При наведении указателя мыши на место, где используется шрифт, в редакторе будут более подсказки:
2.2 Эффективно используйте расширение типа
-
TypeScriptСуществует два способа определения типов в интерфейсе:interface) и введите псевдонимы (type alias). В следующем примере определены те же типы, за исключением синтаксиса:
- И интерфейсы, и псевдонимы типов могут быть расширены:
- Интерфейсы и псевдонимы типов не исключают друг друга, то есть интерфейсы могут расширять псевдонимы типов, а псевдонимы типов также могут расширять интерфейсы:
- TypeScript: Interfaces vs TypesРазница между интерфейсом и псевдонимом типа подробно описана в разделе и не будет здесь подробно рассматриваться.
- Когда выбирать интерфейсы и псевдонимы типов:
- Используется при определении общедоступного API (например, при редактировании библиотеки).
interface, что позволяет пользователям удобно наследовать интерфейс; - При определении свойств компонента (
Props) и статус (State), рекомендуется использоватьtype,потому чтоtypeболее ограничительный; -
typeТипы нельзя редактировать дважды, в то время какinterfaceМожет быть продлен в любое время.
- Используется при определении общедоступного API (например, при редактировании библиотеки).
2.3 Эффективное использование декларационных документов
- Файл объявления должен начинаться с
.d.tsявляется суффиксом. Вообще говоря,TypeScriptбудет анализировать все элементы в проекте*.tsфайл и, следовательно, также содержит файлы, начинающиеся с.d.tsКонец файла манифеста.
- если только
tsconfig.jsonКонфигурация содержитtyping.d.tsфайл, потом все остальное*.tsфайл может получить определения типов в файле объявлений.
2.3.1 Документы-декларации третьих лиц
- когда в
TypeScriptПри использовании сторонней библиотеки в проекте нам необходимо обратиться к ее файлу объявлений, чтобы получить соответствующее завершение кода, подсказки интерфейса и другие функции. - Для большинства сторонних библиотек сообщество определило для нас свои файлы объявлений, и мы можем загрузить и использовать их напрямую. Обычно рекомендуется использовать
@typesУнифицированное управление файлами объявлений сторонних библиотек,@typesСпособ использования очень прост, непосредственно используйтеnpmилиyarnУстановите соответствующий модуль объявлений. кlodashНапример:
2.3.2 Файл пользовательской декларации
- Когда сторонняя библиотека не предоставляет файл объявления, нам нужно написать файл объявления самостоятельно. к
antd-dayjs-webpack-pluginНапример, когда вconfig.tsиспользуется вantd-dayjs-webpack-plugin, если редактор не найдет его файл объявления, произойдет следующая ошибка:
- когда мы используем
yarn add @types/antd-dayjs-webpack-plugin --devПри попытке решить проблему получаю следующую ошибку:
- То есть файл объявления, относящийся к библиотеке, не может быть найден (можно найти вздесьИщите нужный вам файл декларации, если не можете найти, значит его нет).
- Чтобы решить сообщение об ошибке редактора, мы можем использовать другой предоставленный им метод: добавить файл, содержащий
declare module 'antd-dayjs-webpack-plugin';новый файл декларации. Мы также можем не добавлять новые файлы, как было сказано ранее.typing.d.tsПросто добавьте следующее:
глобальная переменная
- когда нам нужно
tsфайл с использованием того жеTypeScriptтип, обычная практика будет вconstant.tsОбъявите соответствующий тип в файле и поместите егоexportвыйти к другимtsдокументimportИспользование, несомненно, приведет к созданию большого количества громоздкого кода. - Как упоминалось ранее, пока
tsconfig.jsonКонфигурация содержит наш пользовательский файл декларации*.d.ts, определения типов в файле объявлений могут использоваться*.tsфайл получен. Таким образом, мы можем объединить несколькоtsГлобальный тип, который должен использовать файл, записан в файле объявления, и вам нужно использовать этот типtsфайл не требуетсяimportможно использовать напрямую.
Пространства имен
- В случае, когда объем кода велик, во избежание различных конфликтов имен переменных в пространство имен можно поместить функцию, класс, интерфейс и т.д. одного и того же модуля.
- существует
tsИспользование файла:
- из-заофициальная документацияСоответствующее содержание файла декларации было подробно представлено и не будет здесь подробно останавливаться, учащиеся, которым это необходимо, могут прочитать его самостоятельно.
2.4 Эффективно используйте новые функции JS, поддерживаемые TypeScript
2.4.1 Необязательная цепочка
-
Необязательная цепочка
?.даES11(ES2020)добавленные функции,TypeScript 3.7Эта функция поддерживается.дополнительная цепочкаЭто может избавить нас от необходимости выполнять избыточные различные предварительные проверки при запросе объектов с несколькими уровнями:
- В противном случае перейдите непосредственно к
user.info.getAge()легко попастьUncaught TypeError: Cannot read property.... - использовалдополнительная цепочка, приведенный выше код станет:
-
дополнительная цепочка— это оператор, который проверяет существование свойства перед попыткой доступа к нему.
TypeScriptпытаясь получить доступuser.infoраньше попытаюсь получить доступuser, только тогда, когдаuserесли неnullни одинundefinedБудет продолжать посещать вниз, еслиuserДаnullилиundefined, то выражение возвращает сразуundefined. - В настоящее время необязательная цепочка поддерживает следующие синтаксические операции:
2.4.2 Нулевой объединяющий оператор
-
Нулевой оператор объединения
??даES12(ES2021)добавленные функции,TypeScript 3.7Эта функция поддерживается. Когда операнд слеваnullилиundefinedКогда , возвращает свой правый операнд, в противном случае возвращает свой левый операнд.
- И логический оператор ИЛИ (
||) разные,||будет иметь левый операнд какfalsyзначение (например,''или0) возвращает правый операнд. То есть, если вы используете||установить значения по умолчанию для некоторых переменных, вы можете столкнуться с неожиданным поведением:
2.5 Эффективно используйте модификаторы доступа
-
TypeScriptОпределение класса позволяет использоватьprivate,protectedа такжеpublicЭти три модификатора доступа объявляют ограничения доступа к членам и проверяются во время компиляции:-
public: общедоступный тип, к которому можно получить доступ внутри класса, подклассов и вне класса.Если модификатор не добавлен, этот уровень доступа используется по умолчанию; -
protected: тип защиты, доступ к которому возможен внутри класса и подкласса, но не вне класса; -
private: закрытый тип, доступный только внутри текущего класса.
-
- Если модификатор не добавлен, по умолчанию
publicУровень доступа:
- Приведенный выше код может получитьTypeScript Playgroundв рабочем состоянии, в
JSобласти, мы можем видеть сбежавшихPersonОпределение класса с удаленными модификаторами доступа:
- Это означает, что экранированный код
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Выведенный тип несовместим, тогда мы можем использовать утверждение типа, синтаксис следующий:
- существует
tsxграмматика(Reactизjsxграмматическийtsверсия) должен использовать первый, т.е.值 as 类型. В то же время, поскольку<>С общим синтаксисом легко конфликтовать, поэтому при использовании утверждения типа рекомендуется использовать единообразно值 as 类型такой синтаксис. - когда
TypeScriptКогда мы не уверены, какого типа переменная типа объединения, мыможет получить доступ только к свойствам или методам, которые являются общими для всех типов этого типа объединения.
- Иногда нам действительно нужно получить доступ к одному из свойств или методов, специфичных для типа, когда мы не уверены в типе, например:
- В приведенном выше примере получите
animal.swimсообщит об ошибке, когда . На этом этапе вы можете использовать утверждения типа дляanimalутверждать какFishтип, вы можете разрешить доступanimal.swimСообщается об ошибке:
- Следует отметить, что утверждения типа могут только «обмануть»
TypeScriptкомпилятор, нельзя избежатьВремя выполненияошибка, вместо этого злоупотребляя утверждениями типаМожет вызвать ошибки времени выполнения:
-
TypeScriptКомпилятор доверяет нашему утверждению, поэтому вызываетswim()Нет ошибки компиляции, когдаCatне наswimметод приведет к ошибке во время выполнения. - 🏁: Будьте осторожны при использовании утверждений типа, старайтесь избегать вызова методов или ссылок на глубокие свойства после утверждений, чтобы уменьшить количество ненужных ошибок во время выполнения.
2.6.2 Типовые ограждения
- Типовые охранники бывают в основном следующими способами:
- typeof: используется для суждения
number,string,booleanилиsymbolчетыре типа; - instanceof: используется для определения принадлежности экземпляра к классу
- in: используется для определения того, принадлежит ли свойство/метод объекту
- typeof: используется для суждения
typeof
- годный к употреблению
typeofреализует сужение типа иneverСвойства типа проверяются всесторонне, как показано в следующем коде:
- Видно, что в конце
elseВнутри ветки мы сужаем его доneverизfooприсвоить явно объявленномуneverПеременные, если все логически правильно, то это должно уметь компилироваться и проходить. Но если однажды ваш коллега изменит егоFooтип:
- Однако он забыл изменить в то же время
controlFlowAnalysisWithNeverПоток управления в методе, на этот разelseразветвленныйfooТип будет сужен доbooleanтип, который не может быть присвоенneverтип, будет сгенерирована ошибка компиляции. используяneverЧтобы избежать появления вновь добавленных типов объединения без соответствующих реализаций, мы можем гарантировать, чтоcontrolFlowAnalysisWithNeverПути всегда исчерпаныFooвсех возможных типов, что гарантирует сохранность кода.
instanceof
- использовать
instanceofОператор сужает тип переменной:
in
- использовать
inПроведите проверку недвижимости:
2.6.3 Двойное утверждение
- Когда мы хотим сделать утверждение типа для значения, нам нужно убедиться, что тип значения, выводимый редактором, перекрывается с новым типом, иначе мы не можем просто сделать утверждение типа, как показано в следующем примере:
- Нужно знать, что любой тип может быть утвержден как
any,а такжеanyМожно утверждать, что он любого типа. - Если мы все еще хотим использовать этот тип, мы можем использовать двойное утверждение:
-
TypeScript 3.0добавил новыйunknownтип, который является более безопаснымanyкопия. Все можно отметить какunknownтипа, ноunkonwnОн должен быть назначен другим типам после оценки типа и условного контроля, и никакая операция не может быть выполнена до оценки типа и условного контроля. - Операция двойного утверждения в нашем примере выше неразумна, просто чтобы проиллюстрировать эффект двойного утверждения.
- 🏁:Никогда не используйте двойные утверждения без крайней необходимости.
- Давайте рассмотрим более распространенный сценарий использования: предположим, мы находимся в
TypeScriptВ проекте аJavaScriptнаписанная библиотека, которая предоставляется через отдельный файл объявленийTypeScriptподдержку, то может быть ситуация:
-
method()существует.d.tsТип параметра, объявленный вSomeType, но поскольку файл объявления не обновляется вовремя, он фактически принимает другой тип параметра, напримерnull.
- В этом случае вы можете использовать
unknownтип для реализации входящегоnull:
- Таким образом, проверка типов компилятора может пройти нормально.
2.7 Эффективно используйте постоянное перечисление
- Постоянное перечисление выполняется с помощью
const enumОпределенные типы перечисления:
- Разница между постоянным перечислением и обычным перечислением заключается в том, что первое будетудален во время компиляции, и не может содержать вычисляемых членов (то есть инициализаторы константных членов перечисления могут содержать только литеральные значения и другие вычисляемые значения перечисления).
- Результат компиляции приведенного выше примера:
- Если вычисляемый элемент включен, на этапе компиляции будет сообщено об ошибке:
- Значение обычного перечисления не вычисляется на этапе компиляции, а сохраняется до этапа выполнения программы.Давайте рассмотрим следующий пример:
- Результат компиляции приведенного выше примера:
- Как видите, когда нам не нужен объект, но нужно значение объекта, мы можем использовать постоянное перечисление, что позволяет избежать создания избыточного кода и косвенных ссылок во время компиляции.
2.8 Эффективно используйте расширенные типы
- Кроме
string,number,booleanВ дополнение к этому базовому типу мы также должны понимать некоторые дополнительные способы использования в объявлениях некоторых типов.
2.8.1 Индекс типа (keyof)
-
keyofпохожий наObject.keys, используемый для получения типа объединения Key в интерфейсе:
2.8.2 Типовые ограничения (расширение)
-
TypeScriptсерединаextendsКлючевые слова отличаются отClassпосле использованияextendsФункция наследования обычно используется в дженериках, и ее основная функция заключается в ограничении дженериков:
-
extendsчасто сkeyofиспользуются вместе, например, у нас естьgetValueМетод специально используется для получения значения объекта, но объект не определен, мы можем использоватьextendsа такжеkeyofСделайте ограничения:
- Когда входящий объект не имеет
key, редактор сообщит об ошибке.
2.8.3 Типовая карта (в)
-
inФункция ключевого слова в основном заключается в отображении типов, обходе существующего интерфейса.keyИли перебирать типы союзов. со встроенным универсальным интерфейсомReadonlyНапример, это реализовано следующим образом:
- Что он делает, так это делает все свойства интерфейса доступными только для чтения:
2.8.3 Тип условия (U ? X : Y)
- Правила синтаксиса для условных типов такие же, как и для троичных выражений, и часто используются в случаях, когда тип неясен:
- Вышеизложенное означает, что если
TдаUПодмножество , является типомX, иначе типY. со встроенным универсальным интерфейсомExtractНапример, это реализовано следующим образом:
-
TypeScriptбуду использоватьneverТипы для представления состояний, которые не должны существовать. Вышеупомянутое означает, что если тип в T существует в U, вернуть его, в противном случае отбросить. - Предположим, у нас есть два класса с тремя публичными свойствами, которые можно передать через
ExtractИзвлеките эти три общедоступных свойства:
2.8.4 Утилиты-дженерики
-
TypesScriptСуществует множество встроенных универсальных инструментов, которые были представлены ранее.Readonly,ExtractОба встроенных дженерика находятся вTypeScriptВстроенныйlib.es5.d.tsопределены в , поэтому их можно использовать напрямую без каких-либо зависимостей.
- Поскольку исходный код может быть напрямую
lib.es5.d.tsКак видно из файла, здесь он не будет подробно останавливаться, ниже описаны функции и методы использования нескольких распространенных парадигм инструментов. -
ExcludeРоль представленного ранееExtractНаоборот, еслиTвведитеUЕсли он не существует, вернуть, в противном случае отказаться.
-
PartialИспользуется, чтобы сделать все свойства интерфейса необязательными:
-
RequiredЭффект точно такой же, какPartialВместо этого измените все необязательные свойства в интерфейсе на обязательные:
-
PickВ основном используется для извлечения некоторых свойств интерфейса:
-
OmitРоль прямо противоположна Pick, в основном используется для удаления определенных свойств интерфейса:
3. Резюме 📝
-
TypeScriptОн очень мощный, расширяет функции редактора (IDE) и предоставляет такие возможности, как завершение кода, подсказки интерфейса, переход к определениям и рефакторинг кода. -
TypeScriptможет иJavaScriptсосуществовать, а значитJavaScriptПроекты могут быть постепенно перенесены вTypeScript. - В этой статье описывается
TypeScriptНесколько распространенных практик в проекте, надеюсь еще не трогалTypeScriptили вправоTypeScriptДрузья, кто еще не знаком с ним, спешите применить его на практике в проекте, и стремиться улучшить ремонтопригодность кода и счастье разработки 💪.