从类型的属性中删除 null 或 undefined

remove null or undefined from properties of a type

我需要声明一个类型,以便从其 属性 类型中删除未定义。

假设我们有:

type Type1{
  prop?: number;
}

type Type2{
  prop: number | undefined;
}

type Type3{
  prop: number;
}

我需要定义一个名为 NoUndefinedField<T> 的泛型类型,以便 NoUndefinedField<Type1> 给出与 Type3 相同的类型和与 NoUndefinedField<Type2>.[=17= 相同的类型]

我试过了

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

但它只适用于 Type2

感谢@artem,解决方案是:

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

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

现在还内置了 NonNullable 类型:

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

https://www.typescriptlang.org/docs/handbook/utility-types.html#nonnullablet

@DShook 的回答不正确(或者说不完整),因为 OP 要求从类型属性中删除 null 和 undefined,而不是从类型本身中删除(一个明显的区别)。

虽然@Fartab 的答案是正确的,但我会添加它,因为现在有 built-in Required 类型,解决方案可以 re-written 为:

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

这将映射类型属性(而不是类型本身),并确保每个都不是;为空或未定义。

从类型中删除 null 和 undefined 与从类型属性中删除它们(使用上述 RequiredProperty 类型)之间的区别示例:

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

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

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

有些答案对我不起作用,我最终得到了基于最热门答案的类似解决方案:

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

TypeScript Playground Example

现在您可以使用 Required 来完全满足您的需求:

Required<Type1>

这将导致所有字段变为 non-optional。可以找到更多详细信息here