typescript 从类型的属性中移除null或undefined

noj0wjuj  于 2022-11-18  发布在  TypeScript
关注(0)|答案(6)|浏览(188)

我需要声明一个类型,以便从其属性类型中删除未定义的。
假设我们有:

type Type1{
  prop?: number;
}

type Type2{
  prop: number | undefined;
}

type Type3{
  prop: number;
}

我需要定义一个名为NoUndefinedField<T>的泛型类型,使NoUndefinedField<Type1>给出与Type3相同的类型和与NoUndefinedField<Type2>相同的类型。
我试过这个

type NoUndefinedField<T> = { [P in keyof T]: Exclude<T[P], null | undefined> };

但它只对Type2有效。

qhhrdooz

qhhrdooz1#

现在还内置了NonNullable类型:

type NonNullable<T> = Exclude<T, null | undefined>;  // Remove null and undefined from T

请参阅类型脚本:文档-实用程序类型

ki1q1bka

ki1q1bka2#

感谢@阿尔特姆,解决方案是:

type NoUndefinedField<T> = { [P in keyof T]-?: NoUndefinedField<NonNullable<T[P]>> };

请注意[P in keyof T]-?中的-?语法,它删除了可选性

nxowjjhe

nxowjjhe3#

@DShook的回答是不正确的(或者说是不完整的),因为OP要求从类型属性中删除null和undefined,而不是从类型本身中删除(一个明显的区别)。
虽然@Fartab的答案是正确的,但我将补充它,因为现在有了内置的Required类型,并且解决方案可以重写为:

type RequiredProperty<T> = { [P in keyof T]: Required<NonNullable<T[P]>>; };

这将Map类型属性(而不是类型本身),并确保每个属性都不是; null或未定义。
从型别移除null和undefined与从型别属性移除它们(使用上述RequiredProperty型别)之间的差异范例:

type Props = {
  prop?: number | null;
};

type RequiredType = NonNullable<Props>; // { prop?: number | null }
type RequiredProps = RequiredProperty<Props>; // { prop: Required<number> } = { prop: number }
q5iwbnjs

q5iwbnjs4#

在@Fartab和@tim.stasse的回答中,有些东西把Date类型的一个属性给弄乱了:

// both:
type NoUndefinedField<T> = {
  [P in keyof T]-?: NoUndefinedField<NonNullable<T[P]>>;
};
type NoUndefinedField<T> = {
  [P in keyof T]-?: NoUndefinedField<Exclude<T[P], null | undefined>>;
};
// throw:
Property '[Symbol.toPrimitive]' is missing in type 'NoUndefinedField<Date>' but required in type 'Date'.ts(2345)
// and
type NoUndefinedField<T> = { [P in keyof T]: Required<NonNullable<T[P]>> };
// throws:
Property '[Symbol.toPrimitive]' is missing in type 'Required<Date>' but required in type 'Date'.ts(2345)

我在没有递归的情况下成功地解决了这个问题:

type NoUndefinedField<T> = {
  [P in keyof T]-?: Exclude<T[P], null | undefined>;
};
vc6uscn9

vc6uscn95#

现在你可以使用Required来完成你所需要的事情:

Required<Type1>

这将导致所有字段变为非可选。更多详细信息可在此处找到

2skhul33

2skhul336#

有些答案对我不起作用,我最终根据排名靠前的答案得出了类似的解决方案:

type RequiredNonNullableObject<T extends object> = { [P in keyof Required<T>]: NonNullable<T[P]>; };

这将导致以下结果:

type ObjectType = {

  startDateExpr?: string | null;
  endDateExpr?: string | null;

  startDate?: Date | null;
  endDate?: Date | null;

}

type Result = RequiredNonNullableObject<ObjectType>;

Result类型等于:

type Result = {
  startDateExpr: string;
  endDateExpr: string;
  startDate: Date;
  endDate: Date;
}

TypeScriptPlayground示例

相关问题