typescript 我怎样才能使一个'部分< T>',但只为空字段?

ohtdti5x  于 2023-02-25  发布在  TypeScript
关注(0)|答案(5)|浏览(104)

我需要一个Partial<T>一样的Map类型,允许我使可空字段可选。我正在键入我们的ORM和它强制未定义为空的可空字段为空。
我想采取一种

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和另一个类型的并集(我希望它能适用于字符串以外的类型),可选字段和未定义值之间的区别很重要。
我能怎么办?

9rygscc1

9rygscc11#

在TypeScript中,让一个类型函数只将 * 一些 * 属性变为可选或非可选实际上是相当烦人的,因为没有简单的方法来描述它。我能想到的最简单的方法是使用具有交集的多个Map类型。只要传入的类型没有索引签名,下面的方法就应该有效(这会变得更复杂):

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] }

请注意,我使用PickExcludeT划分为可空属性和不可空属性,对每个属性执行不同的操作,然后将它们交叉在一起。(即,“我可以将null赋给这个属性吗?”),而不是相反(即,“我可以将这个属性赋给null类型的变量吗?“)。
我还使用泛型参数默认值来使类型操作更简洁(因此我只需将可空属性键名称确定为NP一次),并使最终输出类型更美观(通过在最后执行一个最终Map类型,我得到了一个不表示为交集的类型)。
我们试试看:

interface User {
  email: string
  name: string | null
}

type NPUser = NullablePartial<User>;
// type NPUser = {
//  name?: string | null | undefined;
//  email: string;
// }

在我看来很合理...这和你想要的很接近吗?祝你好运。

6fe3ivhb

6fe3ivhb2#

让我们从查找哪些属性可以为空开始。

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>>;

我们的最终产品是通过将整个Tweak 部分版本与本应不受影响的属性合并而创建的。

type NullablePartial<T> = Partial<T> & Omit<T, NullablePropertyOf<T>>;

当然,方法不止一种,在这个例子中,我把所有的东西都“选择化”,并“要求”所要求的东西,你也可以采取相反的方法:首先选择非空字段,然后选择空字段,然后合并两种类型。2只要适合你就行。

qcbq4gxm

qcbq4gxm3#

只是稍微改变了一下原来的Partial
部分:type Partial<T> = { [P in keyof T]?: T[P] | null };
T可重复部分:type TNullablePartial<T> = { [P in keyof T]?: T[P] | null };

f0brbegy

f0brbegy4#

我想我不确定这和使用可选接口属性之间的区别是什么。
比如:

export interface foo {
   bar?: string;    // nullable
   baz: string;
   bat: boolean;
   etcd?: boolean;  // nullable
}

对你来说不管用吗?

6qftjkof

6qftjkof5#

不确定这是否是您所需要的,但这允许我在接口上同时使用undefined和null

type NullablePartial<T> = {
  [K in keyof T]?: T[keyof T] extends null
    ? null
    : T[K];
};

相关问题