Как устранить проблемы с компиляцией Typescript?

Возьмите следующую стрелочную функцию Typescript:

/**
 * Returns a probably unique component name.
 * 
 * @param baseName a suggested name to make unique.
 * @returns a probably unique name.
 */
export const getUniqueComponentName = (
  baseName
): string => {
  return baseName + Math.round(Math.random() * 10000000)
}

Когда Typescript настроен в tsconfig.json как таковой:

"noImplicitAny": true,

Это правильно приводит к ошибке компиляции:

[ts] Параметр baseName неявно имеет тип any.

Код Visual Studio также достаточно умен, чтобы сообщить вам об этой проблеме во время разработки.

Моя цель - создать хук precommit git, который предотвращает попадание таких ошибок в систему управления версиями. Я пытался сделать это с tslint, husky и lint-staged, используя этот npm script:

"lint": "tslint --project tsconfig.json --config tslint.json"

Однако это не приводит к тому, что tslint обнаруживает ошибку компиляции. Это молча игнорируется.

Затем я попытался добавить правило в tslint.json:

"typedef": [
      true,
      "arrow-parameter"
    ]

Хотя это действительно заставило tslint жаловаться, он также начал жаловаться на анонимные стрелочные функции, где компилятор tsc не жалуется. В этих стрелочных функциях нет необходимости добавлять типы, потому что типы уже были установлены ранее в родительской области (они предполагаются).

В общем, я бы хотел, чтобы tslint в этом случае вел себя так же, как tsc. Каждый раз, когда возникает ошибка, которая может привести к сбою компиляции (например, указанная выше стрелочная функция), я хотел бы предотвратить фиксацию, но без фактической компиляции в Javascript. Это возможно?


person Tom    schedule 19.07.2018    source источник
comment
Будет ли работать tsc --noEmit? По сути, это запуск статического анализатора без генерации JS.   -  person y2bd    schedule 19.07.2018
comment
@ y2bd да, я подтвердил, что работает; это рекомендуемый способ сделать это? помимо запущенного цлинта?   -  person Tom    schedule 19.07.2018
comment
В своем рабочем процессе я обычно делаю обычную сборку и просто отбрасываю артефакты (а также отдельную стадию линта). Если вы находитесь в ситуации, когда это нежелательно, это кажется совершенно нормальным.   -  person y2bd    schedule 19.07.2018
comment
@ y2bd согласно github.com/okonet/lint-staged/issues/412 Невозможно lint-staged запускать tsc только для зафиксированных файлов. Это возможно только в том случае, если вы не передаете флаг p, но тогда все параметры конфигурации игнорируются. Также вы не можете передать конфигурацию paths в качестве аргумента командной строки, поэтому отказ от использования p не является вариантом?   -  person Tom    schedule 19.07.2018
comment
@ y2bd Я назначил награду в 150 человек, если вы не могли бы уточнить мой предыдущий вопрос.   -  person Tom    schedule 22.07.2018


Ответы (2)


Я думаю, что лучше всего запустить tsc --noEmit -p . и отфильтровать вывод на предмет ошибок в измененных файлах. Например, я сохранил следующий скрипт в tsc-some-files:

#!/bin/bash
declare -A include_files
for f in "$@"; do
  include_files["${f#$PWD/}"]=1
done
node_modules/.bin/tsc --noEmit -p . | (
  status=0
  show_continuation=false
  while IFS='' read -r line; do
    case "$line" in
    (' '*)
      if $show_continuation; then
        echo "$line" >&2
      fi
      ;;
    (*)
      file="${line%%(*}"
      if [ -n "${include_files["$file"]}" ]; then
        show_continuation=true
        echo "$line" >&2
        status=1
      else
        show_continuation=false
      fi
      ;;
    esac
  done
  exit $status
)

и установил ./tsc-some-files в качестве моей команды lint-staged, и, похоже, это сработало. (Написание этого на языке программирования, отличном от bash, при желании остается в качестве упражнения для читателя.)

Однако имейте в виду, что редактирование одного файла может привести к ошибке в другом файле (например, если вы изменили тип чего-то, что использует другой файл), поэтому я настоятельно рекомендую вам как можно скорее очистить свой проект от ошибок TypeScript любым необходимы хаки (если вы помечаете их, чтобы вы могли искать их позже), а затем настройте свой хук так, чтобы не требовать ошибок во всем проекте. Фактически, что касается, в частности, noImplicitAny, когда я несколько лет назад перенес проект JavaScript на TypeScript, я написал сценарий, который вставлял явную any везде, где была неявная any ошибка, а затем на досуге исправил явные any. Я могу поделиться сценарием, если вам интересно.

person Matt McCutchen    schedule 26.07.2018
comment
Это запустит tsc для всего проекта, а не только для зафиксированных файлов. - person Tom; 26.07.2018
comment
Что вас беспокоит? Производительность или что в других файлах есть ошибки, которые вы хотите игнорировать, пока эти файлы не будут изменены? - person Matt McCutchen; 26.07.2018
comment
В основном второй случай. Первый чуть-чуть :) - person Tom; 26.07.2018
comment
Обновил ответ. - person Matt McCutchen; 26.07.2018
comment
Спасибо за сценарий. Я пробовал интегрировать его с TS v3 и получаю странные ошибки вроде этой: ./scripts/ts-staged-files.sh: line 4: src/ui/Components/Select/Select.tsx: division by 0 (error token is "/Components/Select/Select.tsx") - person okonetchnikov; 07.11.2018
comment
@okonetchnikov Похоже, что bash пытается рассматривать имя файла как строку, чего не должно происходить, если вы правильно скопировали скрипт, включая строку declare -A. Не могли бы вы опубликовать репозиторий, воспроизводящий проблему? - person Matt McCutchen; 08.11.2018
comment
-A у меня не работает на Mac, поэтому я перешел на -a, полагая, что это то же самое. - person okonetchnikov; 09.11.2018
comment
@okonetchnikov Это твоя проблема. Вам нужно будет либо получить версию bash, которая поддерживает declare -A, либо найти другое решение, например переписать сценарий на языке программирования, который поддерживается в вашей среде. (Я не заинтересован в этой работе прямо сейчас.) - person Matt McCutchen; 10.11.2018

У меня недостаточно репутации, чтобы добавить это в качестве комментария, но любой, кто получает ошибку, похожую на

./scripts/ts-staged-files.sh: line 4: 
   src/ui/Components/Select/Select.tsx: division by 0 
  (error token is "/Components/Select/Select.tsx")

Я внес эту небольшую модификацию в ответ Мэтта Маккатчена, чтобы исправить это.

#!/bin/bash

include_files=()

for f in "$@"; do
  include_files+=("${f#$PWD/}")
done
person jmmendez    schedule 01.12.2018