Тип-охранники, предикаты типов, подписи утверждений и фирменные типы в TS
TypeScript – мощный инструмент для создания простого и предсказуемого кода. Давайте рассмотрим несколько его полезных функций, которые помогут вам писать более качественный код.
Представьте, что мы строим интеллектуальную систему управления зданием, которая будет использоваться в промышленных компаниях и сфере здравоохранения. Система основана на использовании датчиков IoT для мониторинга и поддержания оптимальных условий окружающей среды в различных зонах: офисах, коридорах, операционных залах, складах и т.д.
Мы собираем данные с множества датчиков, чтобы обеспечить энергоэффективность и соблюдение нормативных требований.
Чтобы продемонстрировать полезность различных функций TypeScript, рассмотрим несколько примеров:
- Обработка ошибок и валидация данных:
Представьте, что у нас есть датчик движения, установленный на роботе. Мы хотим записывать данные о движении робота, но перед этим необходимо убедиться, что робот действительно движется, а скорость движения является допустимой (неотрицательной и ненулевой). TypeScript позволяет нам легко реализовать проверку данных и обработку ошибок с помощью тип-охранников, предикатов типов и подписей утверждений.
const sanitizedMotion = structuredClone(motionDto);
assertIsMoving(sanitizedMotion);
assertNotZeroOrNegative(sanitizedMotion.speed);
sanitizedMotion.speed = this.sanitizeSpeed(sanitizedMotion.speed);
// ...
return await this.dbClient.create(sanitizedMotion);
Этот код, используя тип-охранник, убеждается, что скорость робота действительно является допустимым числом. Если скорость отрицательна или равна нулю, то выбрасывается ошибка.
- Пример с использованием предиката типа:
В качестве альтернативы, мы можем предоставить пользователям возможность настроить чувствительность датчика движения. Это позволит избежать ненужной проверки корректности настроек, которая может быть необходима, если уровень чувствительности установлен неправильно. Например, слишком высокая чувствительность может привести к ложным срабатываниям, когда датчик фиксирует движение, которого на самом деле нет.
export async function sanityCheckSensitivity(motionDto: MotionDto) {
if (isStatic(motionDto)) {
const lastMovingRecord =
await motionRepository.getLastMovingRecord(motionDto.deviceId);
const lastMovingDate = DateTime.fromISO(
lastMovingRecord.timestamp,
);
const currentStaticDate = DateTime.fromISO(
motionDto.timestamp.toISOString(),
);
const diff = currentStaticDate.diff(lastMovingDate, 'hours');
if (diff.hours > 12) {
console.warn`Sensitivity level is too low for device ${motionDto.deviceId}!`;
}
return;
}
// Here it knows that the motion data was not static and it was actually sent because of some movements
const lastStaticRecord = await motionRepository.getLastStaticRecord(
motionDto.deviceId,
);
const lastStaticDate = DateTime.fromISO(lastStaticRecord.timestamp);
const currentMovingDate = DateTime.fromISO(
motionDto.timestamp.toISOString(),
);
const diff = currentMovingDate.diff(lastStaticDate, 'hours');
if (diff.hours > 12) {
console.warn`Sensitivity level is too high for device ${motionDto.deviceId}!`;
}
}
- Или что, если вы хотите отправить уведомление о движущемся роботе, который имеет высокое энергопотребление, что-то вроде этого:
export function notifyMeOnMovingHighConsumptionDevice(
motionDto: MotionDto,
meterDto: MeterDto,
) {
if (!isPowerConsumptionHigh(meterDto)) {
return;
}
assertIsMoving(motionDto);
console.warn`Current power consumption for device ${motionDto.deviceId} is high!`;
console.warn`This could be caused because it is moving according to sensor ${motionDto.sensorId} with the speed of ${motionDto.speed}`;
}
В репозитории GH (https://github.com/kasir-barati/clean-code-in-js-ts/blob/6db7688f3faf6f23ff45c456580a3d482ce06aa7/src/index.ts#L86) вы найдете полную реализацию кода, представленного в этой статье.
Если у вас есть предложения по улучшению кода, вы можете оставить комментарий, открыть issue, связаться в социальных сетях или любым другим удобным для вас способом. Все ваши отзывы ценятся.