【问题标题】:Typing dynamic object fields键入动态对象字段
【发布时间】:2020-07-15 19:07:50
【问题描述】:

假设我有一个联合类型的动态对象:

  foo: {[key in 'num' | 'str' | 'obj']: number | string | object};

现在我分配对象属性如下:

  foo.num = 1;
  foo.str = 'text';
  foo.obj = {};

而且它有效。但是,当我尝试访问时:

  foo.num

并使用这个值 f.e.通过总结所有foo.num 属性来减少它 - 我不能因为编译器告诉我foo.num 是联合类型。如何告诉编译器foo.numnumber 的类型?我知道as 有一种方法,但这不是一种优雅的方法。我一直在SOMedium 和其他编程网站寻找答案,但找不到解决方案。

编辑:

这只是一个例子。我的真实情况是这样的。我有一个对象数组,我必须按它们的一个 Enum 类型的属性对其进行分组,然后映射它们。所以我正在做这样的事情:

Object.values(Enum).forEach(
    enum => subjects[enum].next(
        array
            .filter(object => object.type === enum)
            .map(object => object.payload)
    )
);

我虽然最好的方法是创建一个对象,它将存储所有 subjects 但这会使所有 subjectsunion 类型的对象中。如果枚举值由于某种原因发生变化,我只需要更改枚举类型,仅此而已。

【问题讨论】:

  • 您能给我们展示一些您真实案例中的示例代码吗?目前尚不清楚您要做什么,尤其是使用 .next(),它用于生成器函数。
  • 好的,请稍等。
  • 是这样的:codesandbox.io/s/….
  • 我仍然认为您需要手动将每个键映射到每种类型,因为 TypeScript 无法正确键入它。

标签: typescript unions


【解决方案1】:

由于您只有 3 个键,创建一个显式声明每个键的类型的接口是否有意义?

interface Foo {
    num: number;
    str: string;
    obj: object;
}

const foo: Foo = {
    num: 1,
    str: 'text',
    obj: {},
}

console.log(foo.num); // (property) Foo.num: number
console.log(foo.str); // (property) Foo.str: string
console.log(foo.obj); // (property) Foo.obj: object

参见TypeScript playground


根据您在 cmets 中提供的代码,您有一个用作键的枚举。 TypeScript 仍然需要一些手动帮助来为键分配正确的类型:

enum NotificationType {
  FRIEND_REQUEST = "FRIEND_REQUEST",
  NEW_MESSAGE = "NEW_MESSAGE",
  GROUP_CREATED = "GROUP_CREATED",
  GROUP_DELETED = "GROUP_DELETED"
}

interface Group {
  name: string;
  users: object[];
}

interface FriendRequest {
  user: object;
}

interface Message {
  messageContent: string;
}

interface Foo {
    [NotificationType.FRIEND_REQUEST]: FriendRequest[],
    [NotificationType.NEW_MESSAGE]: Message[],
    [NotificationType.GROUP_CREATED]: Group[],
    [NotificationType.GROUP_DELETED]: Group[]
}

const foo: Foo = {
    [NotificationType.FRIEND_REQUEST]: [],
    [NotificationType.NEW_MESSAGE]: [],
    [NotificationType.GROUP_CREATED]: [],
    [NotificationType.GROUP_DELETED]: []
}

console.log(foo[NotificationType.FRIEND_REQUEST]); // FriendRequest[]
console.log(foo[NotificationType.NEW_MESSAGE]);    // Message[]
console.log(foo[NotificationType.GROUP_CREATED]);  // Group[]
console.log(foo[NotificationType.GROUP_DELETED]);  // Group[]

请参阅TypeScript Playground 上的示例。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-06-11
    • 2015-12-20
    • 1970-01-01
    • 2023-02-26
    • 1970-01-01
    • 2020-09-16
    相关资源
    最近更新 更多