Более конкретное подавление ошибок потока

Mar 19 2020
Мы улучшаем подавление ошибок Flow, чтобы они случайно не скрывали ошибки. В следующем году Flow планирует внести множество изменений и улучшений в свою систему типов.
Фото icon0.com с сайта Pexels

Мы улучшаем подавление ошибок Flow, чтобы они случайно не скрывали ошибки.

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

Это может быть проблемой, потому что подавление Flow влияет не только на исходную ошибку, которую вы намеревались подавить. Это снижает способность Flow обнаруживать ошибки. Это является результатом двух свойств: во-первых, подавление потока может быть расположено в любой части ошибки типа, а во-вторых, подавление потока может подавлять любой тип ошибки . Чтобы исправить эти недостатки, мы потребуем, чтобы подавления размещались в том месте вашего кода, где действительно возникает ошибка, и чтобы они включали код ошибки, указывающий тип ошибки, которую вы хотите подавить.

Чтобы понять, что все это означает, давайте углубимся в природу ошибок типов в Flow.

Что такое ошибка типа?

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



function foo(x : number) : void {}
foo("hello");
/* error */
foo("hello");
       ^ Cannot call `foo` with `"hello"` bound to `x` because string [1] is incompatible with number [2].
References:
2: foo("hello");
       ^ [1]
1: function foo(x : number) : void {}
                    ^ [2]

function foo(x : number) : void {}
let y : string = "hello";
foo(y);
/* error */
foo(y);
       ^ Cannot call `foo` with `y` bound to `x` because string [1] is incompatible with number [2].
References:
2: let y : string = "hello";
           ^ [1]
1: function foo(x : number) : void {}
                    ^ [2]

Так что же плохого в подавлении?

Что ж, поскольку подавление может применяться как к первичному, так и к вторичному расположению, размещение //$FlowFixMeкомментария над определением fooподавит ошибки в обоих приведенных выше примерах. Поскольку fooпоявляется как вторичное место в каждой ошибке, которая его использует, это будет означать, что любое использование, fooкоторое приводит к ошибке, будет подавлено этим единственным подавлением, где бы оно ни произошло. Вы сможете вызывать fooс любым количеством аргументов любого типа, и Flow не будет отображать вам никаких ошибок или предупреждений по любому из них. Это снижает доверие пользователей к проверке типов в Flow и позволяет ошибкам, которые в противном случае были бы обнаружены, внедрить в производственную среду.

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

// library file lib.js
function foo(x : number) : void {}
// impl file
const {foo} = require("lib.js");
let y : string = "hello";
// $FlowFixMe
foo(y);

Что мы будем с этим делать?

Чтобы решить эту проблему, мы внесем следующие изменения:

  • Принудительное использование основных местоположений. Мы изменим поведение подавления таким образом, чтобы подавление применялось только к ошибкам, размещенным в их основном месте. Например, вместо того, чтобы позволять вам подавлять недопустимый вызов при определении функции, мы теперь потребуем, чтобы подавление находилось на самом месте вызова. Таким образом, Flow по-прежнему сможет предупреждать вас о других, возможно, недопустимых вызовах функции.
  • Добавьте коды ошибок. Мы также будем добавлять коды ошибок в наши подавления, чтобы они подавляли только ошибки указанного типа. Это предотвратит неожиданное подавление подавления ошибки, которую вы не ожидали встретить.
  • Стандартизируйте синтаксис подавления. Ранее приемлемый синтаксис для подавления ошибок можно было настроить вручную в .flowconfigдля данного проекта, что допускало несовместимый синтаксис подавления в проектах. В рамках вышеуказанных изменений мы также стандартизируем синтаксис подавления; поддерживает только форматы $FlowFixMe[incompatible-type]или $FlowExpectedError[incompatible-type].

Посадочная дистанция

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

  • Чтобы переместить недавно недействительные подавления в их основные места, мы рекомендуем комбинацию утилит add-commentsи, remove-commentsимеющихся в инструменте Flow. При выполнении ./tool remove-commentsбудут удалены все комментарии, которые больше не подавляют ошибку, потому что они находятся не в основном месте, и ./tool add-commentsбудут применяться новые подавления в неподавленных местах. ./toolСкрипт можно получить путем клонирования репозитория потока на GitHub.
  • Подавления без кодов ошибок будут продолжать подавлять любые и все ошибки в их местоположении, но как только мы развернем функцию кодов ошибок, вы сможете добавить правильные коды в свою кодовую базу с помощью процесса, аналогичного описанному выше. Удаление всех ваших старых комментариев и их повторное добавление add-commentsбудет включать код ошибки во вновь добавленный комментарий.