Как определить общий тип в потоке, который имеет все поля, необязательные для указанного типа

Мы можем легко определить общий тип в typescript, который может иметь все поля, необязательные для переданного общего типа. Такой тип запроса очень полезен в определении типа для определения результата запросов mongo, поскольку нам может не понадобиться получать все поля и может проверяться с помощью необязательной спецификации типа.

https://www.typescriptlang.org/docs/handbook/advanced-types.html

interface Person {
    name: string;
    age: number;
}

type Partial<T> = {
    [P in keyof T]?: T[P];
}

const p : Partial<Person> = {
    name:"A"
}

Как определить то же самое с помощью потока. Мы можем использовать $Keys. но не может получить свой тип при определении другого типа, как это было сделано в типе script. - [P в ключе T]: T [P]; Мы не можем получить P в потоке. https://flow.org/en/docs/types/utilities/#toc-keys

type Person = {
    name: string,
    age: number;    
}

type Partial<T> = {
    [$Keys<T>] : 1;  // doubt here how to get type of prop comes in left
}

const p : Partial<Person> = {
    name:"A"
}

Фактически Мы пытаемся написать спецификацию типа для Query. Мы не можем дать null или undefined для не указанных ключей.

type Department = {
    _id : string,
    name : string,
    type : string
}

type Person = {
    _id : string,
    name : string,
    age : number,
    department : Department
}

type Query <T> = {
    [P in keyOf T ]?: 1 | Query<T[P]> 
}

type Document<T> = {
    [P in keyOf T ]?: T[P] | Document<T[P]>     
}

const personDepartments  : Query<Person> = {
    name:1, department :{name:1}
}

Этот запрос вернет некоторый результат, как следует

{_id:"1",name:"abc",department:{name:"xyz"}}

который может иметь тип документа

const a : Document<Person> = {_id:"1",name:"abc",department:{name:"xyz"}}

Таким образом, мы можем написать функцию следующим образом

function getResult<T>(query:Query<T>) : Document<t> {
    // code here to query and get result
}

Это очень просто в TypeScript. Поэтому я думаю, что в Flow также должен быть путь.

Ответ 1

Другим подходом будет "распространение" типа (извините, не могу найти на нем никакой документации, кроме changelog):

type Foo = {
  A: string,
  B: number,
  C: string
};

type Partial<T> = { ...T };

const t: Partial<Foo> = {
  A: 'a'
};

Теперь это действительно частично, и вы можете пропустить клавиши.

Ответ 2

Вы можете приблизиться к $ObjMap<T, F>, который применяет тип функции F к каждому свойству T.

type Foo = {
  A: string,
  B: number,
  C: string
};

function makeOptional<T>(t: T): ?T {
  return t;
}

type PartialFoo = $ObjMap<Foo, typeof makeOptional>;

const t: PartialFoo = {
  A: 'a',
  B: null,
  C: undefined
};

Однако в этом случае вы по-прежнему не можете пропустить клавиши, но можете добавить null или undefined к своим значениям.