Issue
export enum SomeKeys {
FIRST_KEY = 'FIRST_KEY',
SECOND_KEY = 'SECOND_KEY',
}
export const DICT: {
[key in SomeKeys]: {
title: string;
greeter: () => {};
};
} = {
[SomeKeys.FIRST_KEY]: {
title: 'first key title',
greeter: (name: string) => ({ name }),
},
[SomeKeys.SECOND_KEY]: {
title: 'second key title',
greeter: (name: string, age: number) => ({
name,
age,
}),
},
};
Is it possible to create such a dictionary with strongly typed "greeter" function?
So I'd like to use those values as:
const { title, greeter } = DICT[SomeKeys.FIRST_KEY];
const { name } = greeter('Adam');
I hope it's clear enough to understand what's my problem 🙄
Solution
With your explicit typing, TypeScript is taking your word for it that DICT
has homogeneous keys of the type you specify; it erases the type information that you'd otherwise get from the constant dictionary. If you delete the typing, it works.
export const DICT /* typing removed */ = {
[SomeKeys.FIRST_KEY]: {
title: 'first key title',
greeter: (name: string) => ({ name }),
},
[SomeKeys.SECOND_KEY]: {
title: 'second key title',
greeter: (name: string, age: number) => ({
name,
age,
}),
},
};
You can do slightly better with a helper function, which will check the completeness of SomeKeys and will throw if you don't correctly specify the expected fields:
type ExpectedKeyType = {
[key in SomeKeys]: {
title: string;
greeter: unknown;
}
};
function checkKeys<T extends ExpectedKeyType>(t: T) {
return t;
}
export const DICT = checkKeys({
/* snip, same as above */
[SomeKeys.THIRD_KEY]: {
title: 'third key title',
greeter: (age: number) => ({ age }),
},
});
const { title, greeter } = DICT[SomeKeys.THIRD_KEY];
const { age } = greeter(42);
// If you diverge from the value, it won't compile.
export const DICT_WITH_TYPO = checkKeys({
/* snip */
[SomeKeys.THIRD_KEY]: {
title: 'third key title',
egregiousTypo: (age: number) => ({ age }), // error here
},
});
Answered By - Jeff Bowman
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.