如何在流中定义泛型类型,其中所有字段都是可选的指定类型

时间:2018-01-29 05:08:13

标签: typescript flowtype

我们可以非常轻松地在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"
}

如何使用Flow定义相同的内容。我们可以使用$ Keys。但是在定义另一种类型时无法获得其类型,就像我们在类型脚本中所做的那样。 - [T in keyof T]?:T [P];我们无法获得P in Flow。 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中也应该有解决方法。

2 个答案:

答案 0 :(得分:3)

您可以使用$Shape实用程序:

  

复制所提供类型的形状,但标记每个字段可选

  <head>
    <meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link href="https://cdn.bootcss.com/bootstrap/2.3.2/css/bootstrap.min.css" rel="stylesheet">
	<script src="https://cdn.bootcss.com/jquery/1.11.1/jquery.min.js"></script>
    <script src="https://cdn.bootcss.com/bootstrap/2.3.2/js/bootstrap.min.js"></script>

   </head>
   <body>
		test
		<ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu">
		  <li><a tabindex="-1" href="#">Action</a></li>
		  <li><a tabindex="-1" href="#">Another action</a></li>
		  <li><a tabindex="-1" href="#">Something else here</a></li>
		  <li class="divider"></li>
		  <li><a tabindex="-1" href="#">Separated link</a></li>
		</ul>
		
   </body>

另一种方法是&#34;传播&#34;类型(抱歉除了changelog之外无法找到任何文档):

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

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

现在它确实是部分的,你可以跳过键。

答案 1 :(得分: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
};

但是,在这种情况下,您仍然无法跳过密钥,但可以将nullundefined添加到其值中。