drop9dead
@drop9dead

Правильное описание типов для колонок таблицы (Typescript)?

Имеется таблица, в ячейках которой может содержаться текст или ссылка.
Для этих 2 видов ячеек создал 2 типа:

type Column = { label: string; props: string }

type LinkColumn = { type: 'link'; path: string } & Column

Колонка с ссылкой имеет те же свойства, что и обычная колонка + два дополнительных поля link и path.

Для итогового типа колонок объединяю 2 типа:
type TableColumn = Column | LinkColumn

Далее объявляю массив колонок. Тут появляются логические ошибки:
const columns: TableColumn[] = [
	// Правильно, объект типа Column
	{
		label: 'test',
		props: 'test',
	},

	// Правильно, объект типа LinkColumn
	{
		label: 'test',
		props: 'test',
		type: 'link',
		path: 'test',
	},

	// Должна быть ошибка, но TS о ней не сообщает
	// Если нет поля type: 'link', то и поля 'path' быть не должно
	{
		label: 'test',
		props: 'test',
		path: 'test',
	},

	// Должна быть ошибка, но TS о ней не сообщает
	// Если нет поля type: 'path', то и поля 'link' быть не должно
	{
		label: 'test',
		props: 'test',
		type: 'link',
	},
]


Как правильно описать типы колонок, чтобы избежать такого поведения?

И еще непонятно следующее:
type TableColumnKeys = keyof TableColumn // Выводится как "label" | "props"

Получается у типа TableColumn есть только ключи "label" | "props". Почему тогда TS позволяет добавлять в массив объекты с "path" и "link"?
  • Вопрос задан
  • 179 просмотров
Решения вопроса 1
Aetae
@Aetae Куратор тега TypeScript
Тлен
Чтоюы union объектов работал - у него должно быть поле-дискриминатор(поле которое есть в каждом объекте и отличает его от другого), допустим type:
type BaseColumn = { label: string; props: string }

type Column = { type: 'text' } & BaseColumn

type LinkColumn = { type: 'link'; path: string } & BaseColumn

type TableColumn = Column | LinkColumn


keyof для юниона объектов показывает только те поля, которые есть в каждом из них. Это логично, т.к. к типу TableColumn ты не можешь обратиться по полую .link предварительно не сузив тип. union - строгий.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы