TypeScript共享类型的多个对象属性

5

在学习了一些 TypeScript 并询问过之后,我得出了以下用于多个属性的共享对象类型声明。

  • 问题 1:有没有更简单的方法来处理具有共享类型的多个属性?
  • 问题 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'
}
3个回答

3
你创建类型的方式看起来很不错。
至于第二个问题,为什么不使用“Omit”来排除你不感兴趣的属性呢?例如: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”的包含变得多余。

谢谢,但这更多是关于从多个属性对象中排除几个属性。 - ZiiMakc
2
只需要使用 omittype X = Omit<XY, "y"> - pascalpuetz
@pascalpuetz 谢谢,现在只剩下 obj5 的问题了 :) - ZiiMakc

3

问题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问题中对这个话题进行了更详细的解释。

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'
}

1
@RTW 我为 obj5 的解决方案添加了一个类型安全的替代方案。 - pascalpuetz

3

我认为你可以稍微修改一下这个内容。

首先创建记录,然后再进行修改。如果需要键,您总是可以在类型上调用 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',
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接