I have a function that reduces an array of properties and builds an object:
type FieldProps = {
name: string;
value: string;
required: boolean;
styles?: object;
className?: string
}
const fields: FieldProps[] = [
{
name: "firstName",
value: "Bob",
required: true,
styles: { width: "100%"}
},
{
name: "lastName",
value: "Smith",
required: true,
className: "example"
},
{
name: "city",
value: "Tulsa",
required: true,
},
{
name: "state",
value: "OK",
required: true,
},
]
const parseFields = <T extends any[], K extends object = {}>(fields: T): K => {
try {
if (!fields || (fields && fields.length < 0)) throw new Error("You must supply an array of fields!");
const parsedFields = fields.reduce((acc, { name, value }: { name: string, value: string}) => {
switch (name) {
case "city":
case "street":
case "state":
case "suite":
case "zipCode": {
acc["address"] = acc["address"] || {};
if (value) acc.address[name] = value;
break;
}
default: {
acc[name] = value;
break;
}
}
return acc;
}, {} as K);
return parsedFields;
} catch (err) {
throw String(err);
}
};
const userDetails = parseFields(fields);
As of now, hovering over userDetails
is displaying an empty object type({}
), when it ideally should be:
{
"firstName": string,
"lastName": string,
"address": {
"city": string,
"state": string
}
}
How can I refactor the function to take the type FieldProps[]
and have it return a dynamically typed object?
Update
It's super close to being typed with the help of @Mingwei, but I'd essentially like to return the typeof ParseFieldsResult<T>
. For example, I tweaked his playground and I'd like to return the typeof O
. What's silly is that if I copy & move the type ParseFieldsResult<T>
into the return, then it gives me the object type I'd expect see on userDetails
(but with WET code): playground.