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

Вы не можете доверять типам TpeScript, если разрешите любой тип в своей кодовой базе.

Начнем с абсолютного зла - любого типа. Я считаю огромной ошибкой то, что по умолчанию конфигурация компилятора машинописного текста имеет« strict правило, установленное на false ». В результате многие люди, незнакомые с технологиями, оставят все как есть из-за силы значений по умолчанию. Но для нового проекта это ужасная идея , поскольку она уменьшает преимущества TypeScript (что на самом деле произошло и с нашим проектом). Чтобы понять, что я имею в виду, вы можете проверьте примеры ниже:

1. «Любой» может быть отнесен к любому типу.

const b: any = 4;
const z: string = b; // no compile time errors
// some time later somewhere in the code 
z.toLowerCase(); // runtime error!

2. Это нарушает вывод типа. Все операции с «любым» производят «любое»:

const a: number = 10;
const b: any = 4;
const z: string = a + b;
// z is actually type of number
// but compiler now believes that it is a string

Итак, неважно, насколько хороши ваши определения типов в целом. Даже пара «любых» типов в вашей кодовой базе может вызвать недоверие ко всей системе типов.

Вы не можете доверять типам TpeScript, если разрешаете утверждение типа.

Еще одна функция TypeScript, которая может легко сделать вашу систему типов полной лжи, - это утверждения типов. Я считаю, что все утверждения типов в производственном коде должны быть запрещены с помощью правил tslint, кроме утверждения as const. Поэтому:

1. Вы с большей вероятностью выберете ярлык, если это будет легко:

const catFromApi: unknown = {
   meow: () => console.log("meow")
};
// Less than 10 characters to lie TS compiler..
const cat: Dog = catFromApi as Dog;

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

function isCat (obj: unknown): obj is Cat {
   if (typeof obj !== 'object' || obj === null) {
      return false;
   }
   
   // now we with TS compiler know for sure that it is an object.
   const possibleCat: Partial<Cat> = obj; // no errors
   return typeof possibleCat.meow === 'function';
}
if (isCat(catFromApi)) {
   const cat: Cat = catFromApi;
} else {
   throw new Error("Invalid api data, cat is expected.");
}

Да, гораздо больше кода, но гораздо меньше возможностей для ошибки. Также есть некоторые библиотеки, такие как io-ts, которые могут помочь вам написать защиту типов более читаемым и декларативным способом.

2. У вас больше шансов допустить ошибки во время рефакторинга.

interface Cat {
   meow: Function,
   name: string
}
const cat1: Cat = {
   meow: () => "meow",
   name: 'daisy',
   hoof: ''  // that line will produce compile error
}
const cat2: Cat = (<Cat> {
   meow: () => "meow",
   name: 'daisy',
   hoof: ''  // that line will NOT produce compile error
})

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

Это самая важная часть. Люди в мире JS, не имеющие опыта работы со статически типизированными языками, такими как Java, привыкли не заботиться о типах в целом. И многие из них рассматривают типы как необязательную вещь. В результате в каждой сложной ситуации, когда нам нужны некоторые универсальные типы, охранники типов или условные типы, они могут попытаться выполнить утверждение типа или дайте определение любой, не пытаясь понять, что происходит. Создание потенциала для распространения лживых типов в вашей кодовой базе.

Таким образом, такая строгая конфигурация компилятора изначально может иметь некоторое влияние на скорость вашей команды, если они не чувствуют себя комфортно с расширенными типами. Но начальные усилия по улучшению знаний стоят преимуществ звуковой системы шрифтов. И в конечном итоге ваша кодовая база будет менее подвержена ошибкам, особенно если у вас нет 100% покрытия качественным модульным тестированием.

Узнайте больше о TypeScript:

Что это за строгие параметры компилятора в TypeScript: Часть 1

Что это за строгие параметры компилятора в TypeScript: Часть 2