【问题标题】:typescript type conditionals extends object打字稿类型条件扩展对象
【发布时间】:2021-08-17 00:25:21
【问题描述】:

我想有条件类型,某物是一个对象。

type Id = {
    id: number
    obj: {
        x: 5
    }
}

type ObjString<T> = {
    [P in keyof T]:
        T[P] extends Object ? string : T[P]
}


const f: ObjString<Id> = {
    id: 4,
    obj: "xxxx"
}

在这里,obj 属性已正确映射到 f 对象中的字符串,但对于 id 属性,我会收到以下错误消息:

error TS2322: Type 'number' is not assignable to type 'string'.

这意味着T[P] extends Object 对于number 被评估为真。我应该如何构造条件,所以 number 将评估为 false,而 object 将评估为 true?

【问题讨论】:

    标签: typescript conditional-types


    【解决方案1】:

    Object 类型并不真正对应于 TypeScript 中的非基元;相反,它是可以像对象一样被索引的值的类型。这包括像stringnumber 这样的原语,当你对它们进行索引时,它们会得到wrapped with objects(因此支持"hello".toUpperCase()(123).toFixed(2) 之类的东西)。只有nullundefined 在这个意义上不是Objects。 Object in TypeScript is rarely what you want.

    如果您尝试在 TypeScript 中查找表示“非原始”的类型,则可以使用 the object type 代替(以小写 o 开头,而不是大写 O):

    type ObjString<T> = {
      [P in keyof T]:
      T[P] extends object ? string : T[P]
    }
    
    type Z = ObjString<Id>;
    /* type Z = {
        id: number;
        obj: string;
    } */
    
    const f: ObjString<Id> = {
      id: 4,
      obj: "xxxx"
    }
    

    然后一切都按你想要的方式运行。

    请记住,尽管数组和函数也是 objects,因此您可能会遇到一些不良行为,具体取决于您想在那里看到的内容:

    type Hmm = ObjString<{ foo(): string, bar: number[] }>;
    // type Hmm = { foo: string; bar: string; }
    

    Playground link to code

    【讨论】:

      【解决方案2】:

      这是因为Object 的类型太笼统了。 javascript 中的每个原始值都扩展了Object,因为偶数和字符串都有自己的方法。 考虑这个例子:

      type Check1 = string extends Object ? true : false // true
      type Check2 = number extends Object ? true : false // true
      

      我认为从另一个方面来解决问题会更好。您可以检查类型是否为原始类型:

      type Id = {
        id: number
        obj: {
          x: 5
        }
      }
      
      type Primitives = string | number | boolean | bigint | symbol;
      
      type ObjString<T> = {
        [P in keyof T]:
        T[P] extends Primitives ? T[P] : string
      }
      
      const f: ObjString<Id> = {
        id: 4,
        obj: "xxxx"
      }
      
      

      Playground

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-11-06
        • 1970-01-01
        • 2022-01-11
        • 1970-01-01
        • 1970-01-01
        • 2019-05-03
        • 1970-01-01
        • 2018-01-05
        相关资源
        最近更新 更多