Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Preserving type when using Object.keys()

I have an object with typed keys, let's call them Statuses (StatusesType). I need to iterate over the object and pass keys to some method expecting parameter of the same type StatusesType, let it be statusPrinter()

type StatusesType = 'PENDING' | 'APPROVED' | 'REJECTED';
type SomeMap = {
    [key in StatusesType]?: number
}

const STATUSES: SomeMap = {
    PENDING: 5,
    REJECTED: 2,
};

function statusPrinter(val: StatusesType) {
    console.log('- ', val);
}

Object.keys(STATUSES).forEach(status => {
    statusPrinter(status);
});

But when I call statusPrinter(status); TypeScript returns this error

error TS2345: Argument of type 'string' is not assignable to parameter of type 'StatusesType'.

How can I pass this key preserving type?

I know that I can force TS with this statusPrinter(<StatusesType>status); but I think it is the last thing I should do and I would prefer native solution.

Update: If it is not possible to iterate over object keys with Object.keys() preserving type - what options do I have? Is there a way to iterate over keys preserving types at all, and if so - which way is the best? I am not fixing on Object.keys() but I would like to keep original object structure.

Thanks!

like image 685
SmxCde Avatar asked Sep 15 '17 06:09

SmxCde


People also ask

Does object keys preserve order?

In JavaScript there's no guarantee for the order of the object keys. You shouldn't count on that even though the de-facto behavior in most engines is to keep the order and recently ES6 touched upon the order.

What does object keys do in TypeScript?

Object.keys() returns an array whose elements are strings corresponding to the enumerable properties found directly upon object . The ordering of the properties is the same as that given by looping over the properties of the object manually.

How do you define type of key in an object?

Use the keyof typeof syntax to create a type from an object's keys, e.g. type Keys = keyof typeof person . The keyof typeof syntax returns a type that represents all of the object's keys as strings. index.ts.

Are object keys always strings?

Object keys can only be strings, and even though a developer can use other data types to set an object key, JavaScript automatically converts keys to a string a value.


1 Answers

Short and typesafe solution using the built-in ES2015 Map class:

type StatusesType = 'PENDING' | 'APPROVED' | 'REJECTED';

const STATUSES = new Map<StatusesType, number>([
    ['PENDING', 5],
    ['REJECTED', 2],
]);

function statusPrinter(val: StatusesType) {
    console.log('- ', val);
}

STATUSES.forEach((_, status) => statusPrinter(status));
like image 55
ideaboxer Avatar answered Sep 20 '22 16:09

ideaboxer