Как вы можете сравнить $ Shape в потоке с глубоким вложенным объектом?

#reactjs #types #flowtype #flow

#reactjs #типы #тип потока

Вопрос:

Проблема, с которой я сталкиваюсь, заключается в том, что я хочу создать функцию, которая принимает объект, являющийся небольшой частью более крупного объекта, и глубоко объединяет его. Однако я хочу, чтобы он был строго типизирован, чтобы перехватывать, если / когда форма «большого» объекта изменится.

Я включаю надуманный пример ниже.

 /* @flow */

type ContrivedType = {
  nested: {
    name: string,
    optionalValue1?: string,
    optionalValue2?: string,
  }
}

let contrived: ContrivedType = {
  nested: {name: "Required Value"}
}

type UpdateObject = $Shape<ContrivedType>

const update = (updateObject: UpdateObject): void => {
  contrived = {
    ...contrived, 
    ...updateObject,
    nested: {
      ...contrived?.nested, 
      ...updateObject?.nested
    }
  }
}

update({nested: {name: "should work", optionalValue1: "should work"}})
update({nested: {optionalValue1: "won't work"}})
 

Здесь вы можете увидеть результаты

Cannot call 'update' with object literal bound to 'updateObject' because property 'name' is missing in object literal [1] but exists in object type [2] in property 'nested'. [prop-missing]

Как я могу заставить это работать?

Ответ №1:

Вы можете создать свой собственный $DeepShape тип, как показано здесь

Код, который я использовал

 type $DeepShape<O: Object> = Object amp; $Shape<$ObjMap<O, (<V: Object>(V) => $DeepShape<V>) | (<V>(V) => V)>>
 

и из этого потока Github

Вот конечный результат приведенного выше кода:

 /* @flow */

type ContrivedType = {
  nested: {
    name: string,
    optionalValue1?: string,
    optionalValue2?: string,
  }
}

let contrived: ContrivedType = {
  nested: {name: "Required Value"}
}

type $DeepShape<O: Object> = Object amp; $Shape<$ObjMap<O, (<V: Object>(V) => $DeepShape<V>) | (<V>(V) => V)>>

type UpdateObject = $DeepShape<ContrivedType>

const update = (updateObject: UpdateObject): void => {
  contrived = {
    ...contrived, 
    ...updateObject,
    nested: {
      ...contrived?.nested, 
      ...updateObject?.nested
    }
  }
}

update({nested: {name: "should work", optionalValue1: "should work"}})
update({nested: {optionalValue1: "won't work"}})
 

Хотелось бы получить любую обратную связь по любым вопросам или проблемам, которые могут возникнуть у людей.