Оператор Rest с обобщениями в Typescript

#typescript #typescript-typings

#typescript #typescript-типизации

Вопрос:

Рассмотрим следующий код…

Я бы ожидал, что оператор распространения будет допустимым кодом, но в конечном итоге это не так. Я надеюсь, что кто-нибудь, разбирающийся в Typescript, сможет посоветовать, почему это так…

 export default function convertToGlobalFragment<
  T extends basicFragmentRecipe_T
>(
  fragmentFactory: (recipe: T) => configFragment_I,
  recipe: T amp; { matchingRules: globalMatchingRules_T }
): globalConfigFragment_I {

  let {
    matchingRules,
    ...restOfRecipe
  }: { matchingRules: globalMatchingRules_T, restOfRecipe: T } = recipe;

}
 

Код ошибки

 Property 'restOfRecipe' is missing in type 'basicFragmentRecipe_T amp; { matchingRules: globalMatchingRules_T; }' but required in type '{ matchingRules: globalMatchingRules_T; restOfRecipe: T; }'.ts(2741)
 

Ответ №1:

recipe является basicFragmentRecipe_T плюсом { matchingRules: globalMatchingRules_T } , и кажется, что basicFragmentRecipe_T у restOfRecipe него вообще нет prop.

Для назначения необходимо указать тот же целевой тип recipe :

 let {
    matchingRules,
    ...restOfRecipe
  }: { matchingRules: globalMatchingRules_T } amp; T = recipe;
 

Ответ №2:

 let {
    matchingRules,
    ...restOfRecipe
  }: { matchingRules: globalMatchingRules_T, restOfRecipe: T } = recipe;
 

Эта часть неверна, потому что рецепт не содержит свойства, которое называется restOfRecipe — it’s { matchingRules: globalMatchingRules_T } amp; T — where T , которое можно присвоить basicFragmentRecipe_T

Вы можете вытащить restOfRecipe без этого кода — пусть TS сделает всю работу:

   let { matchingRules, ...restOfRecipe } = recipe;
 

Теперь restOfRecipe имеет тип:

введите описание изображения здесь

 Pick<T amp; { matchingRules: globalMatchingRules_T; }, Exclude<keyof T, "matchingRules">>
 

Давайте разберем это.

Тип рецепта — это комбинация T и { matchingRules: globalMatchingRules_T; }

Чтобы получить из этого типа свойства, кроме ‘matchingRules’ — нам нужно исключить matchingRules из T и { matchingRules: globalMatchingRules_T; } . Поскольку последняя часть всегда будет содержать правила сопоставления, мы можем пропустить проверку комбинации и просто посмотреть Exclude<keyof T, "matchingRules" , чтобы получить ключи T без «правил сопоставления».

Наконец, мы затем используем Pick<T, K> для выбора ключей T (без matchingRules ) из типа Recipe , что дает нам результат выше.