Reputation: 3016
I've got a object (let it be frozen so typescript may handle its keys better):
const obj = Object.freeze({
'hello': 64,
'world': 20
}) as {[key: string]: number};
Now I have a function where the user can pick values by their keys:
const pick = (keys: Array<string>): Array<number> => {
const values = [];
for (const key of keys) {
// Check if object contains property-key
if (!(key in obj)) {
throw new Error(`There's no such key: ${key}`);
}
values.push(obj[key]);
}
return values;
};
That's looking good so far and works flawlessly during runtime where I check if the user passed any invalid keys. But how can I tell TS that only keys from obj
can be used?
I could do Array<'hello' | 'world'>
but I'd need to update it any time I add new properties to obj
which is kinda annoying.
Related questions but they all seem to use types whereas I only have a object (which can be frozen if that helps):
type
whereas I'm trying to build a type out of my object)Upvotes: 6
Views: 7671
Reputation: 20162
const obj = Object.freeze({
'hello': 64,
'world': 20
});
const pick = (keys: Array<keyof typeof obj>) {...}
As you can see I have removed as {[key: string]: number};
as it was widening the type, where you wanted to have it strict.
Next things is Array<keyof typeof obj>
I declare here that I accept as argument only array of keys from type of obj
.
Array<keyof typeof obj>
evaluates dynamically into ("hello" | "world")[]
, fortunately as you wanted it will reflect every change in original obj
Upvotes: 13