【问题标题】:Why doesn't typescript undefined type behave same as optional?为什么打字稿未定义类型的行为与可选类型不同?
【发布时间】:2018-05-23 14:18:08
【问题描述】:

假设我们有接口

interface Foo {
  bar: number | undefined;
}

如果我们尝试创建类似 Foo 类型的对象

const foo: Foo = {};

它不会编译,因为缺少属性栏。但是我们说它可以是未定义的,如果我们将它显式设置为未定义,这将起作用,但如果我们根本不设置它,那是完全相同的。不应该和下面的完全一样吗?

interface Foo {
   bar?: number;
}

对我来说这是一个问题,因为如果我们考虑更复杂的例子,我们有一个字段的接口,它可以是泛型类型的可选。就像,如果没有指定泛型类型,那么字段应该是未定义的,如果指定了,那么它应该只是那个类型。例如

interface Foo<T = undefined> {
    bar: T;
    title: string;
}

const foo1: Foo = {
    title: 'TITLE'
};

const foo2: Foo<number> = {
    title: 'title',
    bar: 12
};

foo1 将无法编译,因为缺少属性,但无论如何它必须是未定义的,如果我们明确指定它,它将起作用,但这完全一样。 我最终通过继承解决了这个问题,其中基类没有任何通用参数,并且子类对其进行了严格指定。但我只是好奇是否有人知道以这种方式处理未定义类型的具体原因。因为我自己找不到任何关于它的信息。

【问题讨论】:

标签: typescript


【解决方案1】:

这两种类型签名并不完全等价(尽管它们足够接近,乍一看可能并不明显)!

  • bar?: number 表示该对象可能没有名为bar 的字段。
  • bar: number | undefined 表示对象将始终有一个名为bar 的字段,但该字段的值可能设置undefined

这种差异在某些情况下可能很重要,因为某些运行时行为取决于存在的字段与设置为未定义的字段之间的差异 - 考虑是否在对象上调用了 Object.keys

Object.keys({ bar: undefined }) // returns ["bar"]
Object.keys({})                 // returns []

【讨论】:

    【解决方案2】:

    简单的原因似乎是还没有人实现它。当前类型检查器的实现方式最终需要 undefined 类型的属性,但有一个 proposal 可以以更有意义的方式更改行为,但还没有人得到它。

    使用条件类型可以实现保持类型名称相同并使字段可选的解决方法:

    type Foo<T = undefined> = {
        title: string;
    } & (T extends undefined ? {} : { bar: T});
    
    const foo1: Foo = {
        title: 'TITLE'
    };
    
    const foo2: Foo<number> = {
        title: 'title',
        bar:10
    };
    

    【讨论】:

      【解决方案3】:

      一个可行的解决方案是使用此实用程序类型:

      type KeysOfType<T, SelectedType> = {
        [key in keyof T]: SelectedType extends T[key] ? key : never;
      }[keyof T];
      
      type Optional<T> = Partial<Pick<T, KeysOfType<T, undefined>>>;
      
      type Required<T> = Omit<T, KeysOfType<T, undefined>>;
      
      export type OptionalUndefined<T> = Optional<T> & Required<T>;
      

      例子

      type MyType = {
          foo: string | undefined;
      }
      
      const willFail: MyType = {};
      
      const willNotFail: OptionalUndefined<MyType> = {};
      

      取自https://github.com/Microsoft/TypeScript/issues/12400#issuecomment-758523767

      【讨论】:

        猜你喜欢
        • 2017-08-02
        • 2019-07-26
        • 1970-01-01
        • 1970-01-01
        • 2023-02-07
        • 1970-01-01
        • 2018-10-17
        • 2017-04-13
        • 1970-01-01
        相关资源
        最近更新 更多