Home > Software design >  Create an object type that uses an object's values as the key in the typescript
Create an object type that uses an object's values as the key in the typescript

Time:11-13

I am creating a function called formatAddress which accepts an address object and property map object as input and outputs the mapped address.

function formatAddress(address, map): MappedAddressOutput {
   ...
}

type MappedAddressOutput = AnyObject[typeof AddressMap[keyof typeof AddressMap]];

interface Address {
    addressLine1: string;
    addressLine2: string;
    city: string;
    province: string;
    postalCode: string;
}

const AddressMap = {
    addressLine1: "address1",
    addressLine2: "address2",
    city: "city",
    province: "province",
    postalCode: "postalCode"
};
type IndexSignature = string | number | symbol; 
type AnyObject = { [key: IndexSignature]: any };

If I wish to transform the MappedAddressOutput as the code below:

type MappedAddressOutput = ObjectValueAsKey<AddressMap>

How can I implement ObjectValueAsKey type?

CodePudding user response:

Use a generic type parameter so you can use the given map in the return type:

function formatAddress<To extends Record<keyof Address, string>>(address: Address, map: To): {
    [K in keyof Address as To[K]]: Address[K];
} {
    return Object.entries(address).map(([k, v]) => [map[k as keyof typeof map], v]);
}

Then when you use it, you have to make sure the map is inferred literally. The simplest way to do that is to use as const:

interface Address {
    addressLine1: string;
    addressLine2: string;
    city: string;
    province: string;
    postalCode: string;
}

const exampleMap = {
    addressLine1: "address1",
    addressLine2: "address2",
    city: "city",
    province: "province",
    postalCode: "postalCode"
} as const;

const result = formatAddress({
    addressLine1: "",
    addressLine2: "",
    city: "",
    province: "",
    postalCode: "",
}, exampleMap);

and now the type of result is

{
    address1: string;
    address2: string;
    city: string;
    province: string;
    postalCode: string;
}

Playground

  • Related