Практическое руководство по TS в JS

JavaScript

头图

Я не знаю, сколько поклонников TS сетовали на эту проблему: хотя я очень хочу использовать TS, босс использует только JS. Сегодня я скажу вам, что вы можете без проблем использовать TypeScript в JavaScript, и ваш начальник не будет вас беспокоить.

серия статей

Первая фаза:"Руководство TS Amway"

Этот период:"TS in JS Practice Guide North"

написать впереди

Многие студенты смотрят"Руководство TS Amway"После этого он прокомментировал: "ТС ароматный, но нашему начальнику это не интересно", "Мне интересно, но нужно время, чтобы потихоньку внедрить. Нет возможности". В то время я чувствовал, что мой Амвей не в место, так что я проделал большую работу.После долгой подготовки я написал это продолжение, которое рассказывает о результате моего упорного изучения практики ТС в JS.

Если у вас есть основы TS, это будет плавное чтение. Если у вас нет основы ТС, вы можете кое-что понять (это тоже моя цель), но если она у вас есть, вы поймете глубже. Если вам не нравится TS, эммммммм... просто посмотрите его :P

Эта статья написана для последней версии VSCode (v1.41.0). В случае каких-либо расхождений с другими IDE преимущественную силу имеют официальные возможности IDE.

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

Что, ты пользуешься блокнотом?

-w136

Дружеское напоминание: основная среда зависимостей имеет только последнюю версию VSCode, и дополнительная настройка не требуется. Некоторые основные демонстрации в этой статье, нуждающиеся учащиеся могутэто здесьоказаться

Как это работает

ТС в VSCode

TypeScript — это инструмент, представленный Microsoft в 2012 году. Однако из-за того, что он родился в несвоевременное время, до выхода VSCode, он не получил широкого внимания в Китае.

Есть группа людей, которые осознают, что у JS есть потенциал изменить слабые стороны JS, и начинают принимать и применять эту технологию Многие из этих людей имеют опыт разработки. Они предпочитают преимущества статически типизированных языков, и, что наиболее важно, они используют IDE, такие как Visual Studio, Eclipse, которые поддерживают TypeScript. Но студенты, занимающиеся чистым фронтендом, редко выбирают такую ​​тяжелую IDE. В то время большая часть чистого фронтенда использовала легковесную IDE вроде Sublime, которая имела немного отключенный интеллект (широко известный как умственная отсталость), и они не поддерживали TypeScript, что было похоже на написание кода в Блокноте. Работа с блокнотом может привести к аутизму. Поэтому, когда «большие шишки с полным стеком» шлепнули себя по заднице и ушли, пришедшие на смену одноклассники были несчастны и ненавидели ТС до глубины души.

После выхода VSCode у фронтенд-разработки наконец-то появилась профессиональная облегченная IDE. С ростом популярности VSCode во фронтенд-разработке TS был принят большим количеством фронтенд-разработчиков и начал свою эру. При использовании VSCode для написания JS-кода, нравится вам это или нет, используете ли вы TS или нет, вы непреднамеренно будете наслаждаться удобством, которое оно принесет.

ТС в JS

Не знаю, задумывались ли вы когда-нибудь, зачем играть в JSdocument., VSCode автоматически выведет в нем методы.

document funciton

Это явно относится к сфере возможностей TS, но также влияет на JS?

Фактически, это также цель, которую TS ожидала достичь в начале своего создания: расширенная система типов и поддержка инструментов разработчика. В переводе: продвинутая система типов и поддержка средств разработки. TS сам по себе является надмножеством JS, поэтому некоторая поддержка JS также является одним из его ключевых показателей эффективности.

Возможности TS VSCode в среде JS исходят из библиотеки TS, которую содержит VSCode. VSCode IDE имеет встроенную папку node_modules, содержащую пакеты TypeScript. И в папке TypeScript есть несколько очень простых файлов объявлений api .d.ts.

lib.dom.d.ts

Глядя на эту картинку, много ли знакомых названий методов? Он предоставляет возможности методов, связанных с Dom. Поэтому в самом JS, опираясь на этот документ, можно иметь возможность подсказывать Dom Api.

В JS объем TS на самом деле гораздо больше, чем вы думаете.

Элегантные файлы заголовка

Давайте поговорим об этом файле объявлений .d.ts, который предоставляет возможности хинтинга в JS.

Встроенный файл декларации

Как упоминалось выше, некоторые базовые API создаются непосредственно в VSCode IDE. Еще одна цель TS с самого начала: поддержка современных функций JavaScript. Говоря простым языком: использование современных возможностей JS.

Так что неудивительно, что VSCode имеет встроенные функции Dom и ES2015, ES2016, ES2017... синтаксиса. Однако по умолчанию VSCode поддерживает только возможности ES 2016. Если вам нужен дополнительный синтаксис, вы можете создать новый файл с именем в корневом каталоге.jsconfig.jsonфайл, затем введите следующее:

{
    "compilerOptions": {
        "lib": [
            "dom",
            "esnext"
        ]
    }
}

Вы даже можете получить подсказки по синтаксису для ES2020.

matchAll

Поскольку файл объявлений, который поставляется с VSCode, поддерживает только функции, сформулированные ECMAScript и W3C, но API, которые нам нужны в нашей разработке, намного больше, существует множество сторонних файлов объявлений.

Файл объявления, который поставляется с пакетом

Не указывать запись по умолчанию:

Некоторые файлы JS будут иметь свои собственные файлы объявлений. Пока файл декларации имеет тот же префикс, что и файл JS, VSCode автоматически импортирует файл декларации.

Например:

// urlLib.js
export function url1 (str) {
    return 'url1'
}
export function url2 (str) {
    return 'url1'
}
export function url3 (str) {
    return 'url1'
}
// urlLib.d.ts
export function url1(str: string): string
export function url2(str: string): string
export function url3(str: string): string

.d.ts

Здесь следует отметить, что IDE будет иметь приоритет над типом API, определенным в файле объявления. Если файл объявления не содержит открытого метода, соответствующего файлу .js, IDE не будет подсказывать, что этот метод существует, и даже сообщит об ошибке при включении проверки синтаксиса.

Кроме того, VSCode имеет собственный набор правил порядка для импорта файлов объявлений, аналогичных правилам запроса узла. Если он слишком длинный, он не будет опубликован.кликните сюдаУзнать больше.

Укажите запись по умолчанию:

Файл объявления, который поставляется с пакетом, также может храниться в отдельной папке без исходного кода.Пока запись файла объявления указана в package.json, VSCode автоматически найдет этот файл. Например, в package.json Vue

vue package

существуетtypingsилиtypesУкажите запись в свойствах , когда мы напрямуюimport Vue from 'vue', он будет искать указанный файл объявления.

import vue

Файл декларации от @types

Есть также некоторые пакеты, которые не помещают файлы объявлений в свой собственный каталог, а размещаются в частном домене, выделенном для файлов объявлений. Вероятно, самый известный пакет в частном домене — это @types/node.

Если вы хотите использовать файлы объявлений узла, вам необходимо установить @types/node.

npm i @types/node -D

Таким образом, API-интерфейсы, использующие node.js, обладают интеллектом.

node

Иногда вы можете обнаружить, что он не установлен@types/nodeIDE также будет предлагать API Node.js. То есть потому, что VSCode найдет пакет типов в нескольких глобальных местах по умолчанию, и у вас есть подсказка.

Вам может быть интересно узнать об этом@typesЧто такое домен. Ответ: домен Microsoft. Файлы деклараций, соответствующие спецификациям, могут быть размещены здесь для использования программистами/женщинами по всему миру. Если вы хотите иметь подсказку для node_modules, но в пакете нет файла объявления, вы можетеиди сюда, чтобы найти.

search jquery

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

Приложение: расширение возможностей типов с помощью файлов объявлений .d.ts.

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

Общие компоненты в Teams:

У фронтенд-команды будет много собственных общедоступных методов.Мы можем добавить файлы объявлений для некоторых общедоступных методов, поддерживаемых внутри, чтобы другие могли пользоваться преимуществами интеллектуальных подсказок при их использовании, уменьшая вероятность ошибок кода.

Заявление, такое как следующие документы для URL Lib:

// url.module.d.ts

/**
 * url lib 工具包
 */

/** 格式化url */
export function formatUrl (a: string): string

/** 获取url参数 */
export function getParams (paramName: string): string

Храните файл объявления .d.ts и lib.js в одном и том же каталоге с тем же именем, например, /xxx/url.module.js и /xxx/url.module.d.ts.

можно использовать вот так

import * as urlLib from "./url.module"

demo

IDE автоматически импортирует его для вас.url.module.d.tsфайл декларации.

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

В передней части бизнеса, идиwindowРабота с кипрскими глобальными переменными является обычным явлением. Заполнение и могут быть некоторые инструменты, тестирование и другие функции среды. В этом синтаксисе обычно используется код внутриwindow.XXCompanyLibs.url.formatдля вызова функции. ноwindow.XXCompanyLibsДля каких функций ниже обычно нужно идти в документацию или исходный код отдельно. Когда в команду приходят новые ученики, они будут растеряны, когда им нужно будет использовать эти публичные функции, а потом жалуются в емейле, что это реально неудобно делать.

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

// gbobal.d.ts
interface ILib {
    /** 获取当前环境 */
    getEnv: string
    /** img方法 */
    img: {
        formatImg: (a: string, b: string) => string
    }
    /** url方法 */
    url: {
        formatUrl: (a: string) => string
    }
}

/**
 * xx公司全局变量
 */
declare var XXCompanyLib: ILib // 定义全局变量

demo

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

волшебная записка

Когда дело доходит до комментариев в JS, все сразу думают о//,/* */

Однако то, что я собираюсь представить здесь, это такая аннотация/** */, который является комментарием в спецификации JSDoc.

/** 我是 JSDoc 注释 */
function foo () {}

JSDoc

JSDoc — это спецификация комментариев и инструмент для создания документации, с которым в той или иной степени сталкивались все.

Эту спецификацию приветствуют многие программисты из-за ее красивого формата. Также существует множество интерфейсных библиотек, которые используют его в качестве спецификации аннотации, например lodash.

В дополнение к этому JSDoc имеет некоторые функции, о которых вы, возможно, не знаете, так что давайте начнем здесь.

Какую проблему решает JSDoc:

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

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

function foo (a, b) {
    document.querySelector('xxx') // 这里 IDE 知道 document.querySelector 是什么,以及返回了什么
    console.log(a) // 这里 IDE 不知道 a 是什么,当 any 处理
    console.log(b) // 这里 IDE 也不知道 b 是什么,也当 any 处理
    return a // return any
}

var bar = foo(1, 2) // 由于在 foo 里面不知道 a 是什么,所以 bar 的类型成了 any

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

Все вышеперечисленное можно решить через JSDoc.

Вы знаете JSDoc:

Согласно международной практике, начните с чего-то простого.

Пишем код вfunctionВ это время, для того, чтобы следующие одноклассники, которые подберут яму, не пришли к вам на беду, обычно комментируют.

Использование комментариев в стиле JSDoc выглядит следующим образом:

/**
 * 方法:foo
 * @param {string} name
 */
function foo (name) {
    console.log(name)
}

здесь/** ... */Это типичный синтаксис JSDoc. в@paramУказывает, что метод получаетnameизstringтип параметра.

В IDE, поддерживающих JSDoc, таких как VSCode и WebStorm, при наведении курсора на этот метод будет выдано дружественное приглашение.

demo

JSDoc вы можете не знать:

На основе вышеизложенного давайте дополнительно изучим следующий код.

/**
 * 方法:foo
 * @param {string} name
 */
function foo (name) {
    console.log(name)
    return name
}

/**
 * 方法:bar
 */
function bar (name) {
    console.log(name)
    return name
}

var _foo = foo('name') // _foo 为 string
var _bar = bar('name') // _bar 为 any

вот одинbarметод, менее@paramи вернуть все входные параметры. Давайте посмотрим, какой у них тип возвращаемого значения:

type demo

можно увидеть, иметь@paramизfooПараметры, возвращаемые функцией, также имеют строковый тип.barФункция возвращает любое.

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

С другой стороны, внутри функции есть тип параметраfooаргументы функцииname, IDE дала ему подсказкуstringвозможности внутреннего метода.

string type

Вот как JSDoc решает проблему нехватки типов функций в JS. в JSDoc@paramэтой марки, в{}Середина представляет тип TS.

Связанный@paramизДокументы Нажмите здесь

Аналогично, исходя из вышесказанного, изменим содержимое JSDoc.

/**
 * 方法:foo
 * @param {{firstname: string, nameLength: number}} name
 */
function foo (name) {
    console.log(name)
    return name
}

В этом случае имя в функции не являетсяstring, но обычайobjectТипы. Конечно, когда мы посещаемname, ты получишьfirstnameа такжеnameLengthдва свойства.

demo

Помните «автозапрос файла конфигурации», упомянутый в «Руководстве TS Amway»?

/**
 * webpack配置自动提示
 *
 * 先安装对应的types包: `npm i @types/webpack -D`
 *
 * @type {import('webpack').Configuration}
 */
const config = {}

webpack types

Вот тот, что в JSDoc@typeМаркер, синтаксическая функция которого заключается в назначении указанного типа следующей единице.

Связанный@typeизДокументация нажмите здесь

Так называемый «автоматический запрос файла конфигурации» на самом деле является./node_modules/@types/webpack/index.d.tsв файле декларацииConfigurationtype Тип берется и присваивается следующемуconfigсреди переменных.

重点.jpg

Это также означает, что JSDoc может напрямую использовать файлы объявлений.

Элегантное использование JSDoc:

Когда некоторые студенты используют JSDoc для аннотирования метода, они напишут что-то вроде этого:

/**
 * ajax 请求
 * @example `ajax('url', options)`
 * @param url 请求链接
 * @param options ajax控制参数
 *               .jsonp 登录模式。'common'常规模式;'silent'静默模式;'forced'强制模式;'backendSilent'后台静默
 *               .async 强制登录标志,会忽略当前登录态再跑一次登录 // TODO 待废弃
 *               .methods 跳过三秒内拒绝授权限制
 *               .success 是否忽略本地缓存的登录态,设为true会重新发起登录请求
 * @returns { Promise } 返回一个promise实例
 */
function ajaxOld (url, options) {}

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

ajaxOld gif

Глядя на подсказки IDE, мы даже не знаем, как пользоваться этой функцией.

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

/**
 * ajax方法
 *
 * @example `ajax('url', options)`
 *
 * @typedef {Object} IAjaxOptions
 * @property {boolean} [jsonp] 是否jsonp
 * @property {boolean} [async] 是否async
 * @property {'GET'|'POST'} [methods] 请求方法
 * @property {(options: any)=>void} [success] 成功回调函数
 *
 * @param {string} url url
 * @param {IAjaxOptions} [options] 参数
 * @param { Promise }
 */
function ajaxNew (url, options) {}

Эффект от его использования в VSCode следующий:

ajaxNew demo

Во время использования IDE дает удобные подсказки для параметров.

Здесь два новых тега,@typedefа также@property.

в@typedefЭффект состоит в том, чтобы объявить тип типа (или понять тип как псевдоним), например, вотobjectтип, названныйIAjaxOptions. а также@propertyРоль состоит в том, чтобы объявить свойства, содержащиеся в вышеупомянутых типах, использовании и@paramПоследовательный.

Связанный@typedefизДокументация нажмите здесь

Кстати, в некоторых библиотеках есть много таких методов записи, которые мы обычно используем, но игнорируем, например этотhtml-webpack-plugin

html-webpack-plugin

Заинтересованные студенты могут перейти на github, чтобы узнать

Теги JSDoc, связанные с этим и поддерживаемые VSCode:

  • params
  • typedef
  • property
  • return
  • this
  • constructor

Дополнительные примеры можно найти в JSDoc.Официальный сайтИзолировано.

не используйте его вслепую

Некоторые учащиеся могут чувствовать себя немного неловко, увидев некоторые из приведенных выше примеров. Ваша интуиция остра. Этот метод, отмеченный JSDoc, имеет определенные риски, не используйте его вслепую. Чтобы продвигать сначала, давайте поговорим о проблемах, которые могут быть вызваны его слепым использованием.

вопрос:

  1. полностью ручной Как видно из вышеприведенного примера, это «маркированная» грамматика, перестановка вручную. В крайних случаях вы можете столкнуться с необходимостью писать комментарии и декларации в половине случаев.

  2. Его нелегко поддерживать, и для его ограничения требуются хорошие командные нормы или проектные документы. Некоторые люди могут писать больше, некоторые могут писать меньше, а третьи могут добавлять код без добавления объявлений в JSDoc.

  3. Существует риск запутать область действия intellisense. Если статическая проверка типов не включена, среда IDE полностью примет созданный вами тип. Если вы принудительно указываете тип только для подсказки, которую вы хотите, не говорите, что я сказал вам этот метод (выполнить).

  4. ограниченная способность Самое главное, JSDoc не является идеальным инструментом для дополнения типов в VSCode. Когда вы реализуете некоторые сложные типы, вы можете обнаружить, что эффект неудовлетворителен, не сомневайтесь в себе, это в значительной степени котел VSCode. Бог знает, сколько незабываемых ночей я провел, работая над ним.

Возможно, из-за того, что JSDoc больше используется для создания документов API, а соотношение спроса и предложения неравномерно, поддержка VSCode для JSDoc ограничена, и в его примечаниях к выпуску есть только некоторые прерывистые обновления. Вот несколько проблем, с которыми я столкнулся до сих пор

  • не может поддерживать@private,@protectedЭтот вид модификации тега по-прежнему указывается в подсказке.
  • Вы не можете определить перегрузку функции непосредственно для функции, вам нужно полагаться на форму объекта
  • Многие теги не поддерживаются, например@augments,@mixinПодождите, приведенные на официальном сайте примеры не могут показать ожидаемого эффекта в редакторе VSCode

выгода:

  1. Умение выполнять простые Вместо изменения на .ts вам даже не нужно менять расширение файла.

  2. Менее инвазивный код Возможно, написанные вами 300 строк кода с комментариями не переживут первую упаковку.

  3. не беспокойтесь ни о каком сценарии Большое количество кода JS сам по себе является любым скриптом, как бы вы его ни меняли, это прогресс.

Упомянутые здесь преимущества резко контрастируют с проблемами, возникающими при дооснащении TS. Если вы не можете перейти на TS в своей команде, попробуйте использовать JSDoc.

Предложения по модернизации

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

Отдайте предпочтение «лечению первопричины»:

Сам VSCode имеет возможность логически ассоциироваться в среде JS. Затем мы должны сначала подумать, можем ли мы позволить IDE автоматически распознавать свою ассоциацию, исправляя некоторую логику.

взять каштан

var foo = {
    b: 2
}
foo.a = 1

foo.a // IDE 找不到 'a'

можно изменить на

var foo = {
    a: 1,
    b: 2
}

foo.a // IDE 找到 foo.a

или

var foo = {}
foo.a = 1
foo.b = 2

foo.a // IDE 找到 foo.a

Больше внимания источникам данных из и JS:

Мы знаем, что в VSCode "ctrl + щелчок" эта операция может перейти к части определения текущей переменной или свойства. Позже мы будем называть это поведение "прямым переходом".

JSDoc имеет очень хорошее преимущество перед JS. Среди возможностей, связанных с TS, поведение «непосредственного перехода» в большинстве случаев определяет позицию объявления кода, а не позицию определения. Большинство программистов, работающих с JS, не хотят обращать внимание на объявление объектного кода, но хотят знать, что это за определение. Если использование типа в JS полностью зависит от файлов объявлений .d.ts, каждый «скачок» может отдалить истину еще дальше.

Поэтому на практике его следует использовать с умомtypeof.

var foo = {
    a: 2,
    b: 2
}

/**
 * @param {typeof foo} obj
 */
function bar (obj) {
    obj.a // 「直跳」找到 foo 里定义的 a
}

Открыть проверку JS:

Хотя удобно использовать возможности типов, обеспечиваемые синтаксисом JSDoc, также необходимо обращать внимание на спецификации. Во многих случаях, хотя IDE распознается, но синтаксис не стандартизирован, лучше всего открыть настройки VSCodeCheck JSили в верхней части кода с помощью// @ts-checkзаметки.

Например следующий код:

var foo = {
    a: 2,
    b: 2
}

/** @type { typeof foo } */
var bar = {}

bar.a // ide可以关联到foo里面的a,但是bar并不包含这个属性

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

при включенииCheck JSПосле этого IDE отобразит красную подсказку:

demo

Соответствует закрытию текущего файлаCheck JSВерхний комментарий это// @ts-nocheck, игнорировать следующую строку TS ошибка// @ts-ignore.

Добавлено в начало некоторых демонстраций GIF ранее в этой статье.// @ts-nocheck, во избежание покраснения IDE и помех для понимания.

Добавить тип JSDoc к часто используемым объектам:

Если комментариев слишком много, это может повлиять на удобство чтения, и вы не сможете сразу изменить весь код на элегантный JSDoc. Поэтому рекомендуется добавлять дополнительные комментарии JSDoc только к часто используемым объектам, таким какzepto, глобальные переменные, данные интерфейса и т. д.

Иногда мы используем библиотеку. Вы столкнетесь с конфликтами имен переменных, такими как

var $ = requireFn('zepto')

В большинстве случаев команда реализует собственный интерфейс.requireFnфункция не возвращаетzeptoтип.

В это время, если естьzeptoвведите файл, вы можете сделать это:

/**
 * @typedef { typeof $ } ZeptoStatic // 把 $ 换个名字
 */
/** @type { ZeptoStatic } */ // 再赋予给 $
var $ = require('zepto')

так что все$имеютzeptoспособность типа.

Вместо этого используйте JSDoc для комментирования кода.:

Мы часто используем по привычке//Продолжайте комментировать код, но мы можем изменить стиль комментирования JSDoc, если нам все еще нужны подсказки IDE. Когда VSCode распознает JSDoc, он выдаст вам предустановленное приглашение:

// 这是bar
var bar = 1 // 这是也是bar
/** 这是foo */
var foo = 2

console.log(bar)
console.log(foo)

наведите мышь наconsole.log(xxx)НазадxxxВыше обратите внимание на подсказку IDE:

demo

demo

fooС советами, которые мы написали в JSDoc.

Если вы можете заменить его на .ts, замените его на .ts:

Как я писал в TS Amway Guide. Хотя трансформировать JS в TS сложно, это безопаснее и полнее. Поэтому, если позволяют условия, его следует преобразовать в код ТС, ведь долгая боль не так коротка, как короткая боль.

Насчет того, как трансформироваться в ТС. Это не содержание этой статьи, поэтому я не буду объяснять это. Существует много хороших практик, связанных с этим. Вы можете найти это.

продвинутая практика

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

TS in JS with JSDoc

1. Потерянный тип параметра:

как говорится в названии. Когда входной параметр выходит через метод, а тип теряется, как элегантно установить соединение:

const args = {
    a: 1,
    b: 2
}

const fn = {
    foo: function () {},
    bar: function () {}
}

/**
 * 合并两个作用域
 *
 * @returns { typeof args & typeof fn } // 这里用 returns 指定了返回类型
 */
function someMergeFn (args, fn) {
    // ...
}

const newObj = someMergeFn(args, fn)

newObj.a // 直跳到上面 args.a
newObj.bar // 直跳到上面 fn.bar

gif demo

Как показано в анимации,newObj.aа такжеnewObj.barВышеуказанная ссылка установлена.

Вот через JSDoc@returnsтег завершает тип параметра, так что указанный тип получается после вызова функции.

2. АналогичноrequireТип потери пакетов, вызванный методом:

Многие старые коды имеют свои собственные методы загрузки других пакетов, которые вызываются здесьsomeRequireFnБар. Однако из-за проблемы, аналогичной 1, возвращаемый тип теряется.В настоящее время его можно получить следующими методами, и он имеет возможность «прыгать прямо» между файлами.

// otherService.js
;(function(global, factory){
    factory()
})(this, function () {
    var args = {
        a: 1,
        b: 2
    }
    var fn = {
        foo: function () {},
        bar: function () {}
    }

    /**
     * @returns { typeof args & typeof fn }
     */
    function someFactoryFn () {
        // ...
    }

    var newObj = someFactoryFn()

    return newObj

    module && (module.exports = newObj) // 这里是 TS 暴露模块的语法
})
/**
 * @type { import ('./otherService') } // 这里用 type 指定 newObj 的类型
 */
var newObj = someRequireFn('./otherService')

newObj.a // 直跳到otherService.js的args.a
newObj.bar // 直跳到otherService.js的fn.bar

gif demo

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

module && (module.exports = newObj)

Поскольку синтаксический анализ TS является полным статическим синтаксическим анализом, его не нужно учитывать.module.exportsРасположение в коде не влияет на бизнес-код.

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

3. Более сложные сценарии:

Если JSDoc имеет ограниченные возможности, вы можете напрямую заимствовать более полные возможности TS для реализации, а затем комбинировать JSDoc для выполнения смешанных дублей:

// InterfaceJs.d.ts
export interface INewObj {
    a: number
    b: number
    foo: () => void
    bar: () => void
}
/**
 * @type { import ('./InterfaceJs.d').INewObj } // 手动引入外部的 .d.ts 声明文件
 */
var newObj = someRequireFn('./otherService')

newObj.a // 直跳到InterfaceJs.d.ts定义的args.a
newObj.bar // 直跳到InterfaceJs.d.ts定义的fn.bar

gif demo

Использование TS в Vue

Давайте рассмотрим практику в Vue.

Есть много способов использовать TS в Vue. один черезimportИмпортировано по умолчаниюVueфайл декларации. Одним из них является использование его стиля класса. Другой является наиболее распространенным, черезVueПлагин для Vetur автоматически сопоставляет свой файл объявления.

Здесь, чтобы сказать несколько слов для этой вилки. Когда тыscriptиспользуется в блокеexport default {}Когда этот синтаксис,{}Часть возможности типа связана со справкой плагина в его файле объявления.

vue type

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

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

Причина, по которой Vue имеет возможности TS, заключается в том, чтоvue.d.tsСуществование файла объявления вместе с несколькими другими файлами документирует все возможности Vue. Тогда мы просто проходим@typeВнедрив его, вы можете использовать возможности типов Vue в JS.

Но здесь сделано только полдела. подумай об этом,new Vue()То, что передается внутри, является объектом. из-заvue.d.tsвнутри, перейти кVueизoptionsявляется универсальным объектом, но мы не можем использовать дженерики для объекта, поэтому нам нуженhelperФункция для выполнения, содержание очень простое:

const vueOptionsTypeHelper = function (options) {
    return options
}

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

оказатьсяvue.d.tsкод, учебаnew VueЧто там передается.

export interface VueConstructor<V extends Vue = Vue> {
  new <Data = object, Methods = object, Computed = object, PropNames extends string = never>(options?: ThisTypedComponentOptionsWithArrayProps<V, Data, Methods, Computed, PropNames>): CombinedVueInstance<V, Data, Methods, Computed, Record<PropNames, any>>;
  new <Data = object, Methods = object, Computed = object, Props = object>(options?: ThisTypedComponentOptionsWithRecordProps<V, Data, Methods, Computed, Props>): CombinedVueInstance<V, Data, Methods, Computed, Record<keyof Props, any>>;
  new (options?: ComponentOptions<V>): CombinedVueInstance<V, object, object, object, Record<keyof object, any>>;
// ...
}

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

вoptionsТип типа

ThisTypedComponentOptionsWithRecordProps<V, Data, Methods, Computed, Props>

Удалите его дженерики и зависимости и создайте новый с именемvue.helper.d.tsфайл объявления, содержимое которого следующее:

// vue.helper.d.ts
import Vue from 'vue'
import { ThisTypedComponentOptionsWithRecordProps } from 'vue/types/options'

export type VueComponentOptions = <
  Data = object,
  Methods = object,
  Computed = object,
  Props = object
  >(options?: ThisTypedComponentOptionsWithRecordProps<Vue, Data, Methods, Computed, Props>)
  => object

МодернизацияvueOptionsTypeHelperметод

/**
 * @type { import ('./vue.helper').VueComponentOptions }
 */
const vueOptionsTypeHelper = function (options) {
    return options
}

затем используйтеvueOptionsTypeHelperзаворачиватьoptions,Например

const options = vueOptionsTypeHelper({
    name: 'app',
    components: {
        App,
    },
    data () {
        return {
            shareDialog: false,
            inWxapp: false,
        }
    },
    methods: {
        methods1 () {
            return true
        },
        methods2 () {
            return false
        },
        onclick () {
            console.log(123)
        }
    },
    created () {
        
    },
    mounted () {
        this.methods1()
    },
})

Таким образом, указанныйobjectестьVueвозможность подсказки типа .

gif demo

Вы можете спросить, так какVueУже есть относительно полная практика использования возможностей типов в JS, так что толку от этого?

Вы можете подумать о том, есть ли в вашей команде подобныеVueS рама? Рамка вашей команды - это просто расстояние файла декларации (небольшой голос BB: и написание этой декларации, возможно, придется потратить 95% всего процесса).

Подобных сценариев много, вы можете использовать свою фантазию, и я не буду их здесь повторять.

Суммировать

Контента много, вот краткое содержание.

Способы использования возможностей TS в JS

  1. использовать файл декларации
  2. Использование JSDoc

Эти два метода также могут работать вместе для достижения некоторых сложных эффектов шрифта.

как подать заявку

  1. Написать файлы объявлений для общедоступных компонентов и глобальных переменных
  2. Пишите комментарии JSDoc для пользовательских функций и элегантно дорабатывайте их.
  3. Используйте JSDoc для переменных без области видимости, объектов и т. д.@type, чтобы указать его тип

Меры предосторожности

  1. Не связывайтесь с JSDoc
  2. Попробуйте сделать так, чтобы код «прыгал прямо» туда, где он определен

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

напиши в конце

Когда я показал эту статью своим друзьям вокруг меня, я обычно сообщал о своем истощении по поводу ТС. Может травма была слишком глубокая, может руки на клавиатуре задавило окружающее противостояние, может просто познать жизнь и написать код, незачем жить с собой.

Что мне нравится в TS, так это то, что это автоматические предложения (опять же, пережиток статически типизированных языков). При более глубоком рассмотрении особенности ТС даже компенсируют некоторые мои собственные недостатки, такие как невнимательность. Глубокое чувство ведет к глубокому осознанию. Хотя это немного более громоздко писать, я оцениваю это выше неудобства, поэтому я пойду на это.

Сделайте шаг назад на 10 000 шагов и скажите, что когда вы идете на собеседование, люди спрашивают вас о ТС, вы также можете использовать это, чтобы одурачить его.

乖巧.jpg


Если вы считаете, что этот контент ценен для вас, пожалуйста, поставьте лайк и подпишитесь на нашу фронтенд-команду.Официальный сайтА на нашем официальном аккаунте WeChat (WecTeam) каждую неделю публикуются качественные статьи:

WecTeam