29 сентября 2021 г.

Канал: @cherkashindev

183

**Использование never в TypeScript

**Допустим мы хотим написать компонент диалог. Его размер может задаваться двумя различными способами:

  1. Явно с помощью width и height
  2. Диалог должен принять размер контента, за это отвечает свойство `responsive

`Интерфейс пропсов будет выглядеть как-то так.

interface DialogProps {
  // ... other properties
  width?: number;
  height?: number;
  responsive?: boolean;
}
 
function Dialog({width, height, responsive}: DialogProps) {
  // ...
}
 
```Тут есть несколько проблем:
1. Чтобы передать либо `width` и `height` или только `responsive` , мы пометили все поля как необязательные и теперь мы можем передать неправильный набор полей или не передать ни одного вовсе.
2. Можем передать все параметры одновременно и в таком случае непонятно, должен диалог быть отзывчивым или отобразиться с указанным размером. 
 
Нам нужно реализовать тип, в котором все поля будут обязательными, но который позволит нам передать либо `width` и `height` либо `responsive` , в противном случае мы должны получить ошибку компиляции.
 
Такой интерфейс будет выглядеть вот так:
 
```tsx
type DialogProps = { title: string } & (
  | {
      responsive: boolean;
      width?: never;
      height?: never;
    }
  | {
      responsive?: never;
      width: number;
      height: number;
    }
);
 
```**never** - пустое множество или проще говоря, это тип, которому не может быть присвоено ни одно значение.
 
```tsx
// ✅ correct configuration
const responsive: DialogProps = {
  title: "Responsive Dialog",
  responsive: true
};
 
// ✅ correct 
const withSize: DialogProps = {
  title: "Dialog with Size",
  width: 600,
  height: 500,
  responsive: undefined
};
 
// ❌ incorrect
const incorrect: DialogProps = {
  title: "Incorrect Props Dialog",
  responsive: false,
  width: 600,
  height: 500
};
 
```В третьем примере мы получим ошибку 🎉. На самом деле, мы могли бы использовать `null` или `undefined` вместо `never` , но `never` выглядит более наглядно, потому что `never` по своей сути показывает невозможные сценарии.
 
[Sandbox с примером.](https://codesandbox.io/s/either-or-types-qzxo0?file=/src/short-either-or.ts)
 
**Ещё по теме
**- [Either/Or types in TypeScript](https://maecapozzi.com/either-or-types/)
- [When to use 'never' and 'unknown' in TypeScript](https://blog.logrocket.com/when-to-use-never-and-unknown-in-typescript-5e4d6c5799ad/)
- [TypeScript. Мощь never](https://habr.com/ru/post/471026/)