Reputation: 58863
I have the following code:
type MyDict = {
[k: string]: unknown;
};
function fn<T extends MyDict>(items: T) {
const functionDict: { [k: string]: (val: keyof T) => void } = Object.fromEntries(
Object.keys(items).map((key: keyof T) => [
key,
(val: keyof T) => console.log(val),
]),
);
}
is there a way to declare functionDict
as an object (or a Record<>
) whose keys are explicitly key of T
instead of the generic string
?
For instance, if I call
type MyExtendedDict = MyDict & {
foo: number;
bar: number;
}
fn<MyExtendedDict>({
foo: 1,
bar: 2
})
I want to make explicit that the keys of the dictionary would be "foo" and "bar".
Upvotes: 0
Views: 86
Reputation: 5112
No matter what, it seems that Object.fromEntries
will always have string as keys.
A possible solution:
function fn<T extends Record<string, any>>(items: T) {
const entries = new Map<keyof T, (val: T[keyof T]) => void>(Object.keys(items).map((key: keyof T) => [
key,
(val: T[keyof T]) => console.log(val)
]))
const functionDict = Array.from(entries).reduce((obj, [key, value]) => {
obj[key] = value
return obj
}, {} as Record<keyof T, (val: T[keyof T]) => void>);
return functionDict
}
fn({
foo: 1,
bar: 2
})
What we get from Typescript:
function fn(items: {
foo: number;
bar: number;
}): Record<"foo" | "bar", (val: number) => void>
Upvotes: 1