输入动态对象字段
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.num
是 number
的类型?我知道 as
有一种方法,但这不是优雅的方法。我一直在 SO
、Medium
和其他编程站点中寻找答案,但找不到解决方案。
编辑:
这只是一个例子。我的真实案例是这样的。我有一个对象数组,我必须按其中一个 属性 (枚举类型)进行分组,然后映射它们。所以我正在做这样的事情:
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 仍然需要一些手动帮助来为键分配正确的类型:
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 上的示例。
假设我有一个联合类型的动态对象:
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.num
是 number
的类型?我知道 as
有一种方法,但这不是优雅的方法。我一直在 SO
、Medium
和其他编程站点中寻找答案,但找不到解决方案。
编辑:
这只是一个例子。我的真实案例是这样的。我有一个对象数组,我必须按其中一个 属性 (枚举类型)进行分组,然后映射它们。所以我正在做这样的事情:
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 仍然需要一些手动帮助来为键分配正确的类型:
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 上的示例。