【问题标题】:Typescript multiple object properties with shared typesTypescript 具有共享类型的多个对象属性
【发布时间】:2020-01-03 08:34:59
【问题描述】:

经过一些打字稿的研究和询问,我想出了以下多个属性的共享对象类型声明。

  • 问题 1:对于共享类型的多个 props,是否有更简单的方法?
  • 问题 2:如何解决最后两个示例?

Typescript playground

type StringProps = 'name' | 'surname' | 'color'
type NumberProps = 'age' | 'height'

//Simple type
type Simple = { [key in StringProps]: string };
const obj1: Simple = {
    name: 'Agent',
    surname: 'Smith',
    color: 'red'
}

//Optional type
type Optional = { [key in StringProps]?: string };
const obj2: Optional = {
    name: 'Agent'
}

//Combined optional type
type Combined = { [key in NumberProps]?: number } & Optional;
const obj3: Combined = {
    name: 'Alex',
    height: 2
}

// Property type change
type StringColor = Partial<Record<Exclude<NumberProps, 'color'>, number> & { color?: string }>
const obj4: StringColor = {
    color: 'rgb'
}

// How to add any additional props with unknown keys?
type Additional = { [key: string]: boolean };
const obj5: Optional & Additional = {
   color: 'rgb',
   additional: true
}

// How to exclude Y prop from a type like this?
type XY = { x: string, y: number };
const obj6: XY = {
   x: 'abc',
   y: 1
}

type X = Record<Exclude<XY, 'y'>, number>
const obj7: XY = {
   x: 'abc'
}

【问题讨论】:

    标签: typescript


    【解决方案1】:

    我认为你可以清理一下。

    先做Records再修改,如果需要key可以随时在type上调用keyof

    type Simple = Record<'name' | 'surname' | 'color', string>
    type Numbers = Record<'age' | 'height', number>
    
    // if you need the keys
    type SimpleKeys = keyof Simple // "name" | "surname" | "color"
    type NumbersKeys = keyof Numbers // "age" | "height"
    
    //Simple type
    const obj1: Simple = {
        name: 'Agent',
        surname: 'Smith',
        color: 'red'
    }
    
    //Optional type
    type Optional = Partial<Simple>
    const obj2: Optional = {
        name: 'Agent'
    }
    
    //Combined optional type
    type Combined = Partial<Numbers & Simple>;
    const obj3: Combined = {
        name: 'Alex',
        height: 2
    }
    
    // Property type change
    type StringColor = Partial<Omit<Simple, 'color'> & { color?: string }>
    const obj4: StringColor = {
        color: 'rgb'
    }
    
    // How to exclude Y prop from a type like this?
    type XY = { x: string, y: number };
    // Pick<XY, 'x'> or Omit<XY, 'y'>
    const obj6: Pick<XY, 'x'> = {
       x: 'abc',
    }
    

    【讨论】:

      【解决方案2】:

      问题 1

      类型看起来不错。您可以通过首先创建接口然后使用keyof 来切换它,但这只是个人喜好问题。

      问题 2

      obj5

      对于obj5,您很可能必须将对象的索引签名更改为any,正如所有声明的那样,特定属性必须符合索引签名。

      type Additional = { [key: string]: any };
      const obj5: Optional & Additional = {
         color: 'rgb',
         additional: true
      }
      

      或者,您可以通过一些类型转换来处理此问题,因为您可以声明此类型。但是你不能创建它。因此,您可以将创建的对象类型转换为 any,然后返回到正确的类型,如下所示:

      type Additional = { [key: string]: boolean };
      const obj5: Optional & Additional = {
         color: 'rgb',
         additional: true
      } as any as Optional & Additional;
      

      我在另一个Stackoverflow Question中对这个主题给出了更详细的解释。

      obj6:

      对于obj6,您可以像这样简单地使用Omit 助手:

      type XY = { x: string, y: number };
      const obj6: XY = {
         x: 'abc',
         y: 1
      }
      
      type X = Omit<XY, "y">
      const obj7: XY = {
         x: 'abc'
      }
      

      【讨论】:

      • @RTW 我为obj5 解决方案添加了一个Typesafe 替代方案。
      【解决方案3】:

      您创建类型的方法对我来说看起来不错。

      至于问题二,为什么不用Omit来排除你不感兴趣的属性呢?例如

      type X = Omit<XY, "y">
      const obj7: X = {
         x: 'abc'
      }
      

      至于obj5:

      type Any= { [key: string]: any};
      const obj5: Any = {
         color: 'rgb',
         additional: true
      }
      

      请注意我没有使用“Optional & Any”,因为使用“Any”会使包含“Optional”变得多余。

      【讨论】:

      • 谢谢,但更多的是从多个属性对象中排除一些道具
      • 只需使用omit 然后:type X = Omit&lt;XY, "y"&gt;
      • @pascalpuetz 谢谢,现在只剩下 obj5 问题了 :)
      猜你喜欢
      • 2019-04-03
      • 1970-01-01
      • 2020-05-04
      • 1970-01-01
      • 2017-02-07
      • 2014-07-17
      • 2021-05-24
      • 2020-08-10
      • 1970-01-01
      相关资源
      最近更新 更多