A
arktypeβ€’4w ago
PIat

Accept number in string type

Hello! I'm parsing each value in a form with JSON.parse to convert string values like false to actual booleans. Unfortunately, this introduces the issue, that if someone inputs 123 into a text field, it gets parsed into a number type by JSON.parse. Then if the field is type string. An error is thrown, since number is not assignable to string. How should a type look like, if it should handle such a situation?
120 Replies
ssalbdivad
ssalbdivadβ€’4w ago
Could you write a code snippet showing showing this?
PIat
PIatβ€’4w ago
const formType = type({
intent: "'profile'",
name: 'string>0',
surname: 'string>4',
agree: 'boolean',
}).or({
intent: "'private'",
password: 'string>0',
})

const formData = await request.clone().formData()

// passing a value that would get returned
const convertedData =
{
intent: 'profile',
name: 123,
surname: 'PlatPlat',
agree: true,
} ?? generateFormData(formData)

const formResult = formData && formType(convertedData)
const formType = type({
intent: "'profile'",
name: 'string>0',
surname: 'string>4',
agree: 'boolean',
}).or({
intent: "'private'",
password: 'string>0',
})

const formData = await request.clone().formData()

// passing a value that would get returned
const convertedData =
{
intent: 'profile',
name: 123,
surname: 'PlatPlat',
agree: true,
} ?? generateFormData(formData)

const formResult = formData && formType(convertedData)
Result:
name must be a string (was number)
name must be a string (was number)
TizzySaurus
TizzySaurusβ€’4w ago
What's this doing?
const convertedData =
{
intent: 'profile',
name: 123,
surname: 'PlatPlat',
agree: true,
} ?? generateFormData(formData)
const convertedData =
{
intent: 'profile',
name: 123,
surname: 'PlatPlat',
agree: true,
} ?? generateFormData(formData)
PIat
PIatβ€’4w ago
generateFormData runs JSON.parse on every value. The left-hand site is what it would return given the request
{
intent: 'profile',
name: '123',
surname: 'PlatPlat',
agree: 'true',
}
{
intent: 'profile',
name: '123',
surname: 'PlatPlat',
agree: 'true',
}
TizzySaurus
TizzySaurusβ€’4w ago
So.... just change generateFormData to not JSON.parse when the text field type is "string"? This doesn't seem like an AT issue
PIat
PIatβ€’4w ago
It's not an AT issue, I am asking advice how it could be handled
TizzySaurus
TizzySaurusβ€’4w ago
Right, then this is how ig ^
PIat
PIatβ€’4w ago
I am converting it in such a way, since multipart/form-data has to send everything as strings
TizzySaurus
TizzySaurusβ€’4w ago
You presumably have a way of knowing which input fields are going to be a text type
PIat
PIatβ€’4w ago
Yes
TizzySaurus
TizzySaurusβ€’4w ago
So just have your generateFormData function take that into account In a very verbose way, something like
const generateFormData(obj) => {
const newObj = {}

for (const [key, value] of Object.entries(obj)) {
if (stringTextFields.includes(key)) {
newObj[key] = value
else {
newObj[key] = JSON.parse(value)
}
}
return newObj
}
const generateFormData(obj) => {
const newObj = {}

for (const [key, value] of Object.entries(obj)) {
if (stringTextFields.includes(key)) {
newObj[key] = value
else {
newObj[key] = JSON.parse(value)
}
}
return newObj
}
Or as one line, something like
const generateFormData = (obj) => Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, stringTextFields.includes(k) ? v : JSON.parse(v)]))
const generateFormData = (obj) => Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, stringTextFields.includes(k) ? v : JSON.parse(v)]))
PIat
PIatβ€’4w ago
I guess this could be use for the comparison
formType.get('name').equals('string')
formType.get('name').equals('string')
But will this also work when the type has contraints? (string>0)
TizzySaurus
TizzySaurusβ€’4w ago
Possibly. I'm not familiar with the library you're using for forms Yeah; why wouldn't it? This is all before ArkType
PIat
PIatβ€’4w ago
formType is an Arktype type
const formType = type({
intent: "'profile'",
name: 'string>0',
surname: 'string>4',
agree: 'boolean',
}).or({
intent: "'private'",
password: 'string>0',
})
const formType = type({
intent: "'profile'",
name: 'string>0',
surname: 'string>4',
agree: 'boolean',
}).or({
intent: "'private'",
password: 'string>0',
})
TizzySaurus
TizzySaurusβ€’4w ago
It means that having a name of "123" is valid (which arguably shouldn't be a valid name, but I don't have the context etc.) but it will still apply the constraint of the length being >0 Oh I think I see what you mean now Hmm Let me get an ArkType environment open
Want results from more Discord servers?
Add your server