Comments 29
Но теперь ESLint ругается на нарушение правила no-use-before-define. А менять конфигурацию ESLint в CRA нельзя.
А почему нельзя просто перенести определение Props в начало файла?
WebStorm сворачивает импорты. В результате, когда открываю файл, то первым делом вижу реализацию компонента. А типы по переходу в конец файла [CTRL]+[END]. Привычка.
Неправильная привычка у вас :)
Props
это как входные параметры функции -> идут первыми.
Компонент это возвращаемый результат -> идёт последним
Неправильная привычка у вас
Спорно. Помнится, ещё в Delphi можно было отдельно объявить тип для использования, и описывать его где-нибудь ниже по коду. Ностальгия. Я применяю деструктуризацию для props, т.е. имена аргументов видно сразу. А разглядывать их типы не особо интересно — информационный шум.
Не обязательно. Обычно react-redux'овский mapStateToProps для компонента идёт вместе с экспортом, соответственно рядом с ними же стоить размещать типы параметров. Так что я считаю логичной такую структуру:
// Компонент
class SomeComponent extends Component {
// ...
}
// Экспорт
const mapStateToProps = state => ({
prop: state.section.prop
})
SomeComponent.propTypes = {
prop: React.PropTypes.string
}
export default connect(mapStateToProps)(SomeComponent)
А вообще синтаксис flow позволяет такое:
class SomeComponent extends Component {
props: {
prop1: string,
prop2: number,
}
constructor(props) {
super(props)
// ...
}
}
Перекраивать create-react-app на кастомный конфиг только из-за привычки искать определения типов в конце?
Мне кажется, это слишком радикальное решение.
И во-вторых, no-use-before-define включен тоже не просто так, чтобы вам мешать. Код читается сверху вниз, если нам нужно посмотреть определение какой-то переменной, то его нужно искать выше по тексту. И определение типов тут не исключение.
Перекраивать create-react-app на кастомный конфиг только из-за...
Не только, аппетит приходит во время еды: styled-jsx, module-resolver, tcomb.
no-use-before-define включен тоже не просто так, чтобы вам мешать
Я сразу предупредил, что "хочется странного" — это послание специально для вас.
Babel мне позволяет извращаться, а вы обратно запрещаете. Ну и кого мне слушаться? :)
Create-react-app — это не Babel, и конфигурации не имеет (react-app-rewired не в счет, потому что это неофициальное дополнение).
И я бы не стал отклоняться от его настроек. Сила create-react-app — в единообразии. Все проекты имеют одинаковый набор технологий и используют одинаковый стиль кода. Очень легко вникать в проект, даже если начинал его не я.
Признаю, это была сомнительная самодеятельность. WebStorm и VSCode позволяют сворачивать блоки. К сожалению WebStorm не запоминает состояние (Folding), в отличии от VSCode.
И добавить отдельную директорию для типов. Когда типы разростаются, то файлы получаются очень большие и не информативные. а вот intellisense так же парсит
flow-typed
- npm
- types
- TableRowsType.js
- AppType.js
Вот тут я сомневаюсь. Компоненты стремятся почковаться до атомарного состояния. Чем меньше — тем лучше. Это оправдано, хотя стучать по клаве утомляет. Отсюда и типы уменьшаются. А вот переключать контекст внимания между файлов — только раздражает. Я вкрячил CSS в компоненты посредством styled-jsx — ужасно доволен, например.
Конечно, бывают исключения. Когда один тип используется в нескольких файлах, и недоступен иначе из-за циклического импорта компонентов.
https://github.com/comerc/yobr/blob/master/src/components/Post/Post.js
Это конспект части доклада
Так вот почему текст так похож на стенограмму, с трудом осилил. А многое просто не понял.
Ни когда не слышал про flow поэтому следующие вопросы такие нубские:
И тут на помощь приходит восхитительнейший плагин… tcomb
Это плагин от flow, от babel или от IDE?
Какими IDE поддерживается flow?
Это плагин от flow, от babel или от IDE?
babel-plugin-tcomb — транспайлит код с применением tcomb.
Какими IDE поддерживается flow?
Nuclide точно поддерживает. Очевидно, что Visual Studio не отстает, но этого я не пробовал.
Настройка WebStorm:
Хотя собирался давно, но решился переехать на Flow после этой замечательной публикации: Зачем использовать статические типы в JavaScript? (Преимущества и недостатки).
Во второй гораздо сильнее вывод типов и strictNullChecks
function b(c: number | undefined) {
c.toExponential(); // Error: Object is possibly undefined.
if (typeof (c) !== "undefined") {
c.toExponential(); // No error
}
}
function d(c: number) {
// CODE
}
b(1);
d(undefined); // Error: Argument of type 'undefined' is not assignable to parameter of type 'number'.
Также очень вкусный keyof
Flow классная штука, flow+tcomb — наверное, ещё круче.
Но всё-таки печалит тот факт, что некоторые вещи он не распознаёт корректно :-(
Вот примеры кода, на который ругается flow, но которые допускаются typescript-ом:
/* @flow */
type Person = {name: string, email: string};
type Bug = {id: string, assignee: ?Person};
var newBug: Bug = {id:'bug1', assignee: null};
if (newBug.assignee) {
console.log(newBug.assignee.name);
console.log(newBug.assignee.email);
}
/* @flow */
function syncOp(y: number): number {
return y;
}
function asyncToSyc(x: ?number) {
if (x) {
setTimeout(() => syncOp(x), 100);
}
}
Согласен, что в некоторых случаях такие конструкции могут породить ошибки, но конкретно эти примеры содержат вполне безопасный код.
И это печально, что flow не смотря на "гораздо строгий и гораздо более мощный вывод типов, чем у TypeScript-а" не может разделять случаи, когда такое поведение безопасно, а когда — нет.
И вместо написания логики приложения, приходится выискивать способы, позволяющие flow мириться с твоим кодом =(
передача внутренних полей после проверки наличия объекта
Проверил, вот так работает без ругани:
type Person = {name: string, email: string};
type Bug = {id: string, assignee: ?Person};
var newBug: Bug = {id:'bug1', assignee: null};
if (newBug.assignee) {
var assignee = newBug.assignee;
console.log(assignee.name);
console.log(assignee.email);
}
асинхронный вызов после проверки наличия переменной
Это тоже легко обойти исправлением типа. Наверно тут можно сделать скидку, что Flow сыроват?
Ещё один косяк нашёл: https://github.com/facebook/flow/issues/3742
Победил property children not found in props of React element
type Props = {
children?: typeof React.Element,
}
И вместо написания логики приложения, приходится выискивать способы, позволяющие flow мириться с твоим кодом =(
Закончил сегодня переезд с PropTypes на Flow. На очереди редюсеры. И по ощущениям пляски вокруг Flow оправданы (я тоже очень не люблю, когда мне навязывают что-то сверх необходимого, похерил по этой причине redux-form, например). Выявлено несколько ошибок, которых не замечал раньше. Только WebStorm тормозит опять, зараза. Как с eslint-ом было, пока не отрубил все лишнее.
Покажите проблемный участок кода. Будем работать. :)
Мы честно попытались, грубо говоря, переименовать проект из JS в TS — оно не заработало. Оно не компилируется, потому что некоторые вещи, с точки зрения TypeScript-а являются некорректными. Это не означает, что TypeScript — плохой язык, но продвигаться на идее надмножества, и подводить меня так, TypeScript — я не ожидал.
Вы неверно понимаете эту идею. TS является надмножеством JS, т.к. полностью поддерживает синтаксис и семантику последнего. Но поскольку TS призван обеспечить статическую типизацию, т.е. является более строгим с т.з. type safety, разумеется, простое изменение расширения файла не работает. Иначе какой смысл переходить на TS?
Тем не менее, разработчики языка учли проблемы миграции и поэтому ввели в конфиг всякие noImplicitAny, allowUnreachableCode и прочие ослабляющие параметры. Проще говоря, включите их все — и простого переименования будет достаточно.
И тут на помощь приходит восхитительнейший плагин, который для меня является киллер-фичей, почему сейчас я выберу Flow, а не TypeScript
Поверхностный гуглеж предолжил мне, как минимум, это: Runtypes, Reflec-TS. Наконец, есть генерация в JSON Schema, на котором построено много runtime-валидаторов.
Flow + tcomb = типизированный JS