【问题标题】:remove null or undefined from properties of a type从类型的属性中删除 null 或 undefined
【发布时间】: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

【问题讨论】:

标签: typescript types null undefined


【解决方案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]——这个有效:stackoverflow.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 }
    

    【讨论】:

    • 重写的解决方案不会是递归的,对吧?
    猜你喜欢
    • 2022-10-13
    • 2022-10-13
    • 1970-01-01
    • 1970-01-01
    • 2017-06-26
    • 2017-09-24
    • 2016-10-29
    • 2015-08-12
    • 1970-01-01
    相关资源
    最近更新 更多