英文:
TypeScript generics are not working for Record?
问题
我有这个 keyBy
函数:
export function keyBy<Key extends string | number, T>(items: T[] | undefined, extractId: (item: T) => Key): Record<Key, T> {
const obj: Record<Key, T> = {};
if (items) {
items.forEach(item => {
const id = extractId(item);
obj[id] = item;
});
}
return obj;
}
它可以用来将对象数组转换为这些对象的字典,按您想要的方式进行键控。例如:
const users = [user1, user2, ...];
const usersById = keyBy(users, u => u.id);
现在我想要更改此函数,使其不仅适用于数字键(如 id),还适用于字符串键:
export function keyBy<Key extends string | number, T>(items: T[] | undefined, extractId: (item: T) => Key): Record<Key, T> {
const obj: Record<Key, T> = {};
if (items) {
items.forEach(item => {
const id = extractId(item);
obj[id] = item;
});
}
return obj;
}
这会引发错误 Type '{}' is not assignable to type 'Record<Key, T>'. ts(2322)
。为什么不起作用?
我认为问题在于现在每个 id
都可以是字符串或数字,而我想要的是所有的 id 都是字符串或数字,但当然它们都是相同的类型。
英文:
I have this keyBy
function:
export function keyBy<T>(items: T[] | undefined, extractId: (item: T) => number): Record<number, T> {
const obj: Record<number, T> = {};
if (items) {
items.forEach(item => {
const id = extractId(item);
obj[id] = item;
});
}
return obj;
}
It can be used to turn an array of objects into a dictionary of these objects, keyed by whatever you want. For example:
const users = [user1, user2, ...]l
const usersById = keyBy(users, u => u.id);
Now I want to change this function to not only work with numeric keys like ids, but also with strings:
export function keyBy<Key extends string | number, T>(items: T[] | undefined, extractId: (item: T) => Key): Record<Key, T> {
const obj: Record<Key, T> = {};
if (items) {
items.forEach(item => {
const id = extractId(item);
obj[id] = item;
});
}
return obj;
}
This gives the error Type '{}' is not assignable to type 'Record<Key, T>'. ts(2322)
. Why is this not working?
I think the problem is that now every id
can be either a string or a number, whereas what I want is that all ids are either a string or a number, but of course they are all the same type.
答案1
得分: 1
你不能将一个空对象分配给具有可枚举键的Record
:
> 注意:我不确定它是否被称为“可枚举”。
> 然而,在这个帖子中,“可枚举”意味着所有的值都是已知的,比如"a" | "b"
或1 | 2 | 3
,并且string
或number
不是“可枚举”。
const obj1: Record<"id", number> = {}
// 类型“{}”中缺少属性“'id'”,但在类型“Record<"id", number>”中是必需的。
const obj2: Record<string, number> = {}
// OK
在你的keyBy
函数中,可以将可枚举值传递给Key
泛型参数,这会导致空对象分配问题。
最简单的方法就是使用as
关键字将它转换成你想要的类型:
const obj = {} as Record<Key, T>;
英文:
You can not assign an empty object to a Record
with enumerable keys:
> Note: I am not sure it is called "enumerable".
> However, in this post, "enumerable" means all value are known like "a" | "b"
or 1 | 2 | 3
, and string
or number
is not "enumerable"
const obj1: Record<"id", number> = {}
// Property 'id' is missing in type '{}' but required in type 'Record<"id", number>'.
const obj2: Record<string, number> = {}
// OK
In your keyBy
function, it is possible to pass enumerable into Key
generic parameter, and that cause the empty object assignment issue.
The most simple way is just use as
keyword to convert it to what you want:
const obj = {} as Record<Key, T>;
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论