我需要像Partial<T>
这样的映射类型,该类型允许我将可空字段设为可选。我正在输入ORM,它在可为空的字段上将undefined强制为null。
我想选择一种
interface User {
email: string
name: string | null
}
然后
interface User {
email: string
name?: string | null
}
我尝试了
type NullablePartial<T> = { [P in keyof T]: T[P] extends null ? T[P] | undefined : T[P] }
但是extends null
不适用于null
和另一种类型的并集(并且我理想地希望它与字符串一起使用)。可选字段和未定义值之间的区别很重要。
我该怎么办?
答案 0 :(得分:5)
在TypeScript中,使类型函数仅将 some 个属性设置为可选或非可选实际上是很烦人的,因为没有简单的方法来描述它。我认为最简单的方法是将多个mapped types与intersection一起使用。只要您传入的类型没有索引签名(它会变得更加复杂),这应该可以工作:
type NullablePartial<
T,
NK extends keyof T = { [K in keyof T]: null extends T[K] ? K : never }[keyof T],
NP = Partial<Pick<T, NK>> & Pick<T, Exclude<keyof T, NK>>
> = { [K in keyof NP]: NP[K] }
请注意,我正在使用Pick
和Exclude
将T
分为可空属性和不可空属性,分别对它们进行不同的处理,然后将它们相交重新走到一起。确定可为空的属性与检查是否null extends T[K]
(即“我可以将null
分配给该属性”)有关,而不是相反(即“我可以将此属性分配给类型为{的变量) {1}}”)。
我还使用generic parameter defaults来简化类型的操作(因此,我只需一次将可空属性键名称确定为null
即可),并使最终输出类型在美学上更令人愉悦(通过在最后执行一个最终的映射类型,我得到了一种不表示为交集的类型。)
让我们尝试一下:
NP
对我来说合理...接近您想要的吗?祝你好运。
答案 1 :(得分:1)
让我们从查找哪些属性可以为空开始。
type NullablePropertyOf<T> = {
[K in keyof T]: null extends T[K]
? K
: never
}[keyof T]
我们需要修改可为空的属性,但其余部分不受影响。为了在我们的转换中忽略不可为空的变量,我们将需要著名的Omit
助手。
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
我们的最终产品是通过合并整个T
的 weak (部分)版本和应该保持不受影响的属性而创建的。
type NullablePartial<T> = Partial<T> & Omit<T, NullablePropertyOf<T>>;
当然,有多种方法可以做到这一点。在此示例中,我可选化所有内容,并要求需要什么。您可以采取相反的方法:首先选择不可为空的字段,然后对可为空的字段进行可选设置,然后合并这两种类型。随便什么。
答案 2 :(得分:0)
我想我不确定这与使用可选接口属性之间的区别。
类似的东西:
export interface foo {
bar?: string; // nullable
baz: string;
bat: boolean;
etcd?: boolean; // nullable
}
在您的情况下不行吗?