Let's say we have object literal like:
export const SOURCE = {
UNKNOWN: 'Unknown',
WEB: 'Web',
MOBILE: 'Mobile',
...
} as const;
and
export const OTHER_SOURCE = {
UNKNOWN: 0,
WEB: 1,
MOBILE: 2, // values might be not sequential or incrementing at all
...
} as const;
OTHER_SOURCE.UNKNOWN // inferred to 0
How to constrain second object literal so it has keys from SOURCE
but the values are still inferred as literals, not numbers like below:
type ConstraintType = {
[key in keyof typeof USER_SOURCE]: number; // how to infer (and possibly still force numbers) numeric values from the second object?
};
export const OTHER_SOURCE: ConstraintType = { ... } as const;
OTHER_SOURCE.UNKNOWN // inferred to number ]
Thank you for help and clarifications.
CodePudding user response:
If you specify the type of a variable, that is it's final type, so as long as the expression on the right is assignable to it, everything is fine.
If you want to capture capture the types from the object literal assigned to OTHER_SOURCE
but also constrain it to have the same properties, you can use a function
export const SOURCE = {
UNKNOWN: 'Unknown',
WEB: 'Web',
MOBILE: 'Mobile',
} as const;
function makeSource<T extends Record<keyof typeof SOURCE, V>, V extends number>(o: T): Readonly<T> {
return o
}
const OTHER_SOURCE = makeSource( {
UNKNOWN: 0,
WEB: 1,
MOBILE: 2, // values might be not sequential or incrementing at all
});
OTHER_SOURCE.UNKNOWN // 1