typescriptstatic-typing

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!


Solution

  • 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));