serge
serge

Reputation: 15239

Convert Array<string> to Record<Enum> in TypeScript

Having

export enum PropertyCode {
  _D = '_D',
  ABCO = 'ABCO',
  ACC = 'ACC',
  // ... etc

I have a function that should return a Record<PropertyCode, any>

public getProperties(): Record<PropertyCode, any> {

    let propertyArray: [PropertyCode, any][] = this.propertyControls?.map(
        (x) => [x.value.propertyCode, x.value.value]) ?? [];

    return propertyArray // [string, any][] ==>??? Record<PropertyCode, any> 
}

I have a compile error :

Type '[PropertyCode, any][]' is missing the following properties from type 'Record<PropertyCode, any>': _D, ABCO, ACC, ACCO, and 255 more.

How should I convert the array to Record, without explicitly filling all 255 enum codes?

Upvotes: 1

Views: 818

Answers (2)

Jonathan
Jonathan

Reputation: 7551

As @captain-yossarian correctly notes, you can't use map, since it doesn't return a Record. You'll need to do it yourself, and also decide what to do in case of a duplicate keys. Below example shows it, both without and with using array.reduce (I personally don't find it adds to readability, YMMV).

Playground link

enum PropertyCode {
    _D = '_D',
    ABCO = 'ABCO',
    ACC = 'ACC',
    // ... etc
}

interface PropertyControl {
    value: {
        propertyCode: PropertyCode;
        value: string;
    }
}

const propertyControls: PropertyControl[] = [
    { value: { propertyCode: PropertyCode._D, value: 'b' } },
    // ...etc
];

function getProperties(): Record<PropertyCode, any> {
    const acc = {} as Record<PropertyCode, any>;
    for (const curr of propertyControls) {
        if (acc[curr.value.propertyCode]) {
            throw `duplicate propertyCode ${curr.value.propertyCode}`;
        }
        acc[curr.value.propertyCode] = curr.value.value;
    }

    return acc;
}

function getPropertiesUsingReduce(): Record<PropertyCode, any> {
    return propertyControls.reduce((acc, curr) => {
        if (acc[curr.value.propertyCode]) {
            throw `duplicate propertyCode ${curr.value.propertyCode}`;
        }
        acc[curr.value.propertyCode] = curr.value.value;
        return acc;
    }, {} as Record<PropertyCode, any>);
}

console.log(getProperties());
console.log(getPropertiesUsingReduce());

Upvotes: 1

Tobias S.
Tobias S.

Reputation: 23835

You should try it with .reduce:

return propertyArray.reduce((acc, curr) => {
  acc[curr[0]] = curr[1]
  return acc
}, {} as Record<PropertyCode, any>) 

Playground

Upvotes: 1

Related Questions