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

Posted

技术标签:

【中文标题】从类型的属性中删除 null 或 undefined【英文标题】:remove null or undefined from properties of a type 【发布时间】:2019-04-02 15:37:44 【问题描述】:

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

假设我们有:

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

【问题讨论】:

Type1 你需要to remove optional modifier 很棒的@artem,这正是我想要的。 【参考方案1】:

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

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

【讨论】:

【参考方案2】:

现在还内置了 NonNullable 类型:

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

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

【讨论】:

很遗憾,如果您没有启用--strictNullChecks,它不会从类型中排除null...【参考方案3】:

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

【讨论】:

谢谢,这很好用。在使用用户定义的属性类型时,我在使用其他答案时也遇到了问题。【参考方案4】:

感谢@artem,解决方案是:

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

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

【讨论】:

这正是我所期望的答案,过滤了现有的界面。谢谢! 非常感谢。我想知道-? 是什么。你在哪里找到这个规范?我总是先看 TS 的文档,但我觉得找东西不容易。 嗨尼古拉斯。是的,这很难找到。两年前,@artem 告诉我存在这样的运营商。 缺少一些东西,我得到了Type 'NoUndefinedField&lt;Uint8Array&gt;' is missing the following properties from type 'Uint8Array': [Symbol.iterator], [Symbol.toStringTag]——这个有效:***.com/a/61766383/544779【参考方案5】:

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

虽然@Fartab 的回答是正确的,我补充一下,因为现在有内置的Required 类型,解决方案可以重写为:

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

这将映射类型属性(而不是类型本身),并确保每个都不是; 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 

【讨论】:

重写的解决方案不会是递归的,对吧?

以上是关于从类型的属性中删除 null 或 undefined的主要内容,如果未能解决你的问题,请参考以下文章

如何在猫鼬中为具有孩子的属性分配“null”或“undefined”

React报错之ref返回undefined或null

JS的作用域

JS基本类型-引用类型-深浅拷贝

id 属性返回 null 或 undefined [重复]

DeepPartial:使用 null 而不是 undefined