TypeScript стал одним из необходимых навыков для современного веб разработчика. В 2019 он вошел в ТОП-10 наиболее используемых языков на GitHub, его поддержку полностью добавили в Create react app, и можно найти массу других свидетельств роста его популярности. В то же время такие языки, как Java и C продолжают сдавать позиции.
Когда мы говорим о преимуществах TypeScript, на ум обычно приходит следующий список:
- TypeScript поддерживает статическую типизацию
- TypeScript делает код проще для чтения и понимания
- TypeScript помогает избежать множества болезненных багов, которые обычно совершают разработчики, благодаря проверке типов в коде
- TypeScript поощряет разработчиков следовать лучшим ООП практикам
- Как следствие вышеперечисленного — TypeScript экономит время разработчиков
Интересно, что все пункты этого списка принимаются на веру без критического взгляда. Сегодня я предлагаю Вам рассмотреть эти пункты внимательней и выяснить, действительно ли они настолько полезны для нас.
Поскольку главной задачей TypeScript является уменьшение количества багов, давайте определимся, почему это так важно? Ответ прост: чем меньше багов — тем меньше дорогостоящего времени разработчиков и тестировщиков мы потратим, следовательно — получим стоящий продукт за меньшие деньги и он начнет приносить доход раньше.
Помня об этом, давайте выясним, как TypeScript может помочь нам улучшить нашу продуктивность и эффективность.
Статическая типизация — волшебная таблетка от багов?
Главная фича TypeScript — поддержка статической типизации. Среди разработчиков распространено убеждение, будто динамическая типизация — источник чуть ли не всех проблем JavaScript разработчиков.
Я гадаю, что плохого люди находят в динамической типизации? Почему на другие динамические языки, например, Python и Ruby, не обрушивается такой шквал критики? Могу лишь предполагать, что проблема не столько в динамической типизации, сколько в приведении типов в JavaScript. Действительно, иногда может очень неприятно удивить код типа такого:
Но это проблема скорее плохого знания JavaScript, а не самого языка. Представьте, что у вас есть мощная спортивная машина. Но ваши водительские навыки достаточно посредственные. Вы будете требовать от производителя машины внести изменения, чтобы уменьшить максимальную скорость машины или научитесь продвинутому вождению и станете выдающимся профессионалом? То, что предлагает нам TypeScript — ограничить возможности динамической типизации вместо того, чтобы как следует выучить JavaScript.
Еще один вопрос к противникам динамической типизации — если статическая типизация так хороша, почему мы все еще встечаем баги в коде, написанном на Java и C#? Да, мы можем отловить эти ошибки на этапе компиляции, но, давайте будем честны, этого недостаточно. Мы должны следовать SOLID принципам и другим лучшим практикам, чтобы обеспечить качественный код. И снова — это относится в большей степени к знаниям и квалификации программистов, чем к языку программирования.
Действительно ли легче читается TypeScript код?
Приведу 2 примера Redux Thunk:
const getUsers = async dispatch => {
//...
try {
const users = await APIService.get('/users')
dispatch(successGetUsers(users))
} catch(err) {
dispatch(failedGetUsers(err))
}
}
и тоже самое на TypeScript:
const getUsers = (): ThunkAction<void, {}, {}, AnyAction> =>
async (dispatch: ThunkDispatch<{}, {}, AnyAction>) => {
//...
try {
const users: User[] = await APIService.get('/users')
dispatch(successGetUsers(users))
} catch(err) {
dispatch(failedGetUsers(err))
}
}
Что значат все эти дженерики? Зачем в них 2 пустых объекта? Сколько времени мы должны потратить на чтение документации, чтобы во всем этом разобраться? Хорошо, это еще нормально для Redux Thunk, поскольку это очень популярная middleware для Redux, у них отличная команда поддержки и документация. Но что, если нам придется поддерживать код, который не имеет всего этого?
Больше не будет трудноуловимых багов?
В предыдущем примере Вы увидели, как TypeScript делает код более многословным. Как известно, чем больше и сложнее система — тем больше вероятность ошибки. Помимо тех ошибок, которые мы могли допустить в JavaScript коде, мы должны еще следить за тем, чтобы не сделать опечатку в интерфейсах, ошибку в дженериках, и т.д. Справедливости ради стоит заметить, что компилятор поможет быстро найти и исправить такие ошибки, но без TypeScript мы бы вообще с ними не столкнулись.
Следование лучшим практикам ООП
Как мы знаем, мы должны следовать лучшим практикам, если хотим писать качественный, легко масштабируемый и поддерживаемый код. И TypeScript может нам в этом помочь. Звучит отлично, давайте рассмотрим пример из Express:
userRoute.js
router.get('/users', (req, res) => {
//get users from DB
res.json(users)
})
router.post('/users', (req, res) => {
//create user
res.json(userCreated)
})
userRoute.ts
class UserRouter {
public router = express.Router()
public address = '/users'
constructor() {
this.initRoutes()
}
initRoutes() {
this.router.get(this.address, this.getUsers)
this.router.post(this.addressm this.createUser)
}
getUsers(req: express.Request, res: express.Response) {
//get uesrs from DB
res.json(users)
}
createUser(req: express.Request, res: express.Response) {
//create user
res.json(userCreated)
}
}
Первое, что бросается в глаза — опять пишется больше кода. Мы используем классы, чтобы писать в ООП стиле. Нам придется потом создавать экземпляры этих классов. В добавок, мы можем использовать интерфейсы, статические типы и другие конструкции. И чтобы это все не превратилось в полнейший хаос, нам не остается ничего, кроме как использовать best practices. И это то, что называется: «поощрение разработчиков к использованию лучших ООП практик».
Когда разработчики проголосовали за простые, гибкие и динамичные языки, такие как JavaScript и Python, когда парадигма функционального программирования показала свои преимущества и способность решать некоторые задачи более изящно и эффективно (и в JavaScript мы можем использовать оба подхода), TypeScript подталкивает нас к тому, чтобы писать код по-старинке в стиле ООП Java и C#.
Подводя итог, мы увидели, что TypeScript в действительности не экономит наше время, он ни защищает нас от большого количества багов, ни увеличивает нашу производительность. Более того, он требует написания большего количества кода, дополнительной конфигурации, type definition файлов, траты времени на чтение дополнительной документации. Новичок скорее напишет, может, не идеальное, но работающее приложение на JavaScript или Ruby, пока мы будем писать отличное TypeScript приложение в соотвествии со всеми принципами. А потом он наймет нас переписывать его стартап, где мы сможем использовать TypeScript, чтобы сделать все правильно.
Забавно видеть, как массивные, многословные и усложненные языки уходят, не выдержав конкуренции с более динамичными и простыми, а затем последние отказываются от всего, что помогло им так быстро развиться, и стремяться стать тяжеловеснее, многословнее и сложнее.
Я вижу это так:
Окей, мы больше не хотим Java, хотим JavaScript. Но нам не нравится JavaScript таким, как он есть, поэтому давайте сделаем его немножечко более похожим на Java. Отлично, теперь у нас есть все, что было в Java, при этом это не Java. Погнали!
Автор: tunikov