Отдельное пересечение между объектом и универсальным c объектом в TypeScript - PullRequest
1 голос
/ 04 марта 2020

Проблема

У меня есть значение, которое является пересечением между родовыми c object A и { _id: string }.

Я хотел снова разделите это пересечение и верните _id отдельно от остальных (в кортеже).

Итак, я попробовал следующее (что по логике должно работать):

function splitDataAndId<A extends object>(a: A & { _id: string }): [string, A] {
  const { _id, ...data } = a;
  return [_id, data]; // type error
}

Это производит ошибка следующего типа:

TS2322: Type 'Pick<A & { _id: string; }, Exclude<keyof A, "_id">>' is not assignable to 
type 'A'. 'Pick<A & { _id: string; }, Exclude<keyof A, "_id">>' is assignable to the constraint of 
type 'A', but 'A' could be instantiated with a different subtype of constraint 'object'.

Вопрос

Можно ли решить эту проблему путем улучшения типов или изменения реализации?

1 Ответ

2 голосов
/ 04 марта 2020

Может быть исправлено только на уровне типа. Рассмотрим:

function splitDataAndId<A extends { _id: string }>(a: A): [string, Omit<A, '_id'>] {
  const { _id, ...data } = a;
  return [_id, data]; // is ok
}

Проблема, с которой вы столкнулись, связана с отсутствием связи между вновь вычисляемым типом A & { _id: string } и самим A. Вы можете понять это, как если бы вы вводили дополнительную переменную на уровне типа. Если мы преобразуем тип A непосредственно с начала, то все здесь совпадает с реализацией. Ограничение на наличие ключа _id помещается в тип generi c, а не в тип аргумента.

Учтите, что я использую A и выполняю преобразование на A только с помощью Omit<A, '_id'>, что действительно тип уровня эквивалентен преобразованию уровня значения (оба удаляют _id из исходной структуры)

ссылка на игровую площадку

...