sindresorhus / ow

Function argument validation for humans
https://sindresorhus.com/ow/
MIT License
3.8k stars 105 forks source link

correct pattern for optional 'required' properties? #251

Open chr4ss12 opened 1 year ago

chr4ss12 commented 1 year ago

given the following structure:

{
     onlyIfNeverHadPremiumBefore?: boolean;
     onlyBrandNewUsers?: boolean;

  params: {
     messageContentId?: string;
     titleContentId?: string;

     userId: string;
     template?: object;

     message?: string;
     title?: string;
  }

I would like to do conditional validation based on the fact that messageContentId&titleContentId should exist both at once, or title&message should exist,

I'll let the code do the talking:

 const commonParams = {
            onlyIfNeverHadPremiumBefore: ow.optional.boolean,
            onlyBrandNewUsers: ow.optional.boolean
        };

        const commonInsideParams = {
            userId: ow.string,
            template: ow.optional.object
        };

        ow(data, ow.any(
            ow.object.exactShape({
                ...commonParams,

                params: ow.object.exactShape({
                    textContentId: ow.string,
                    titleContentId: ow.string,

                    ...commonInsideParams
                })
            }),

            ow.object.exactShape({
                ...commonParams,

                params: ow.object.exactShape({
                    text: ow.string,
                    title: ow.string,

                    ...commonInsideParams
                }),

            })));

I wonder if there is a better way? this is pretty unreadable, I'd prefer something a long of lines:

    ow(data, 
        ow.object.exactShape({

            onlyIfNeverHadPremiumBefore: ow.optional.boolean,
            onlyBrandNewUsers: ow.optional.boolean,

            params: ow.object.exactShape({

                userId: ow.string,
                template: ow.optional.object,

                ...(ow.any(
                    ow.object.exactShape({
                        titleContentId: ow.string,
                        messageContentId: ow.string,
                    }),

                    ow.object.exactShape({
                        title: ow.string,
                        message: ow.string,
                    }))
            })
        }),
    });