输入动态对象字段

Typing dynamic object fields

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

  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 和其他编程站点中寻找答案,但找不到解决方案。

编辑:

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

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

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

既然你只有 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


根据您在评论中提供的代码,您有一个用作键的枚举。 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 上的示例。