I have been working with a couple of schemas, where one contains an array of the other as a value. For example,
const ActionSchema = {id: z.string(), name: z.string(), description: z.string()}
const PersonSchema = { id: z.string(), actions: ActionSchema.array().optional() }
type Person = z.infer<typeof PersonSchema>;
However, when I access a Person, I prefer the actions property to be in the form of a single object. The transformation would look like this.
const actionsArray = [
{action: 'run', id: '1234', description: 'run up'},
{action: 'kick', id: '5334', description: 'kick it'},
{action: 'punch', id: '2236', description: 'punch it'},
{action: 'drop', id: '3434', description: 'drop it'},
];
Resulting in:
{
run: {action: 'run', id: '1234', description: 'run up'},
kick: {action: 'kick', id: '5334', description: 'kick it'},
...
}
To achieve this, I made adjustments to my PersonSchema as follows,
const PersonSchema = {
id: z.string(),
actions: ActionSchema.array().optional().transform((actions) => {
return actions
? Object.fromEntries(actions.map((action) => [action.name, action]))
: undefined;
}), }
This modification works perfectly when outputting the Person object.
The issue arises when trying to create a new Person using typescript like this,
const newPerson:Person = {
id: 'PER1234',
actions: actionsArray }
An error occurs stating: Index signature for type 'string' is missing in type '{id: z.string(), name: z.string(), description: z.string()} ' The expected type comes from property 'actions' which is declared here on type '{ id: z.string(), actions: ActionSchema.array().optional() }
I understand that the properties are not aligned due to the transform function applied on actions. My goal is for the schema to accept an Actions array as input during the creation of a new Person, and then modify it to the desired format after processing, when accessing or printing the Person.
I apologize if this explanation is unclear. Any assistance would be greatly appreciated.
I have attempted various solutions to resolve the error. While the code "works", typescript does not validate it. I can create the new Person using the actions array and specifying it as any, like this,
const newPerson:Person = {
id: 'PER1234',
actions: actionsArray as any
}
However, I am hoping to avoid using 'as any' if possible.