假设我有一个所有属性都是可选的类型:
type T = {
x?: number;
y?: string;
z?: number;
...
}
有没有一种方法可以构造一个类型,允许所有类型T的值,但至少需要一个属性?例如:
let a: NotEmpty<T> = { z: 1 }; // ok
a = {}; // error
当然,这样做的一种方法是将至少具有一个所需属性的所有组合合并,但是当属性的数量很大时,这会变得有点尴尬。有没有更一般的方法?
假设我有一个所有属性都是可选的类型:
type T = {
x?: number;
y?: string;
z?: number;
...
}
有没有一种方法可以构造一个类型,允许所有类型T的值,但至少需要一个属性?例如:
let a: NotEmpty<T> = { z: 1 }; // ok
a = {}; // error
当然,这样做的一种方法是将至少具有一个所需属性的所有组合合并,但是当属性的数量很大时,这会变得有点尴尬。有没有更一般的方法?
1条答案
按热度按时间o2gm4chl1#
您所谈论的“至少具有一个必需属性的所有组合”的联合并不太难编写,特别是因为您可以编写
NotEmpty<T>
实用程序类型来自动计算它。并且该类型的每个属性键只有一个联合成员,因此它可以很好地扩展属性的数量(它不是阶乘或组合爆炸或任何东西)。这里有一种写法:
所以一个
NotEmpty<T>
是T
与某物相交,所以我们知道,至少NotEmpty<T>
是T
的一个子类型。我们用来交叉的东西,是一个 * 分布式对象类型 *(如在microsoft/TypeScript#47109中创造的),一个mapped type,我们立即将index与其所有键一起得到一个并集。在上面,我们得到
keyof T
中每个K
的{[P in K]-?: T[K]}
的并集。{[P in K]-?: T[K]}
类型等价于Required<Pick<T, K>>
(参见Required
和Pick
实用程序类型):一个明确具有来自T
的K
属性的对象。所以整件事就是:
NotEmpty<T>
是一个T
,它也被称为具有T
中的属性中的 * 一些 * 定义的属性。让我们在你的例子中测试一下:
看起来不错,让我们确保它的行为符合预期:
看起来也不错!
Playground链接到代码