After overcoming all obstacles, I am finally ready to unleash the first version of my form validation library.
Below is a snippet of the code (simplified for clarity)
interface Validation {
name: string
message: string
params?: Record<string, any>
test: (value: any, params?: any) => boolean
}
class MixedSchema<T> {
type!: T
validations: Validation[] = []
required(message?: string) {
this.validations.push({
name: 'required',
message: message,
test: (value: any) => {
return value === '' ? false : true
},
})
return this
}
oneOf(arrayOfValues: any[], message?: string) {
type Params = { arrayOfValues: any[] }
this.validations.push({
name: 'oneOf',
params: { arrayOfValues },
message: message,
test: (value: any, params: Params) => {
return params.arrayOfValues.includes(value)
},
})
return this
}
}
// more code...
If everything goes well, I should see the expected result.
https://i.sstatic.net/mA3Xv.png
However, achieving the most accurate typing remains a challenge. Ideally, it should resemble the schema defined for form
, like this:
interface HowNeedsToBe {
email: string
age: number | undefined
gender: 'male' | 'female'
color: 'red' | 'blue' | 'green' | undefined
}
The logic might involve setting undefined
in the absence of required
, and substituting arguments with T
from MixedSchema<T>
in case of oneOf
. But figuring out how to propagate this back to MixedSchema<T>
seems daunting.
I've explored TypeScript's map and generics features extensively, but applying them practically has proven challenging.
You can experiment with the code in the TS playground.