Comments (13)
This is absolutely awful. You wrote a data validator which can't even do the most basic validations and to do them, I have to write practically the entire validation myself, and add on the extra things myself.
What on earth are you thinking? This lack of basic functionality makes this library worthless :/ If I have to write basic validations myself, then there is absolutely no benefit to using this library since practically EVERY REAL WORLD USE, would require this basic, yet missing feature. 2 years later.....
from superstruct.
@vladshcherbin so I think the issue is that Superstruct encourages doing things a little differently. With other validation libraries (eg. Joi) you'll often define "types" inline, by doing things like:
username: Joi.string().alphanum().min(3).max(30).required()
Superstruct doesn't do this, by design. Instead it encourages you to define you data types upfront, in one place, and then refer to them elsewhere. So instead of defining the specific validation inline, you do something like:
const struct = superstruct({
types: {
username: v => typeof v === 'string' && v.length > 3 && v.length < 30 && /[a-zA-Z0-9]+/.test(v)
}
})
const User = struct({
id: 'number',
name: 'string',
username: 'username',
...
})
This way you have a single source of truth for data types, and can re-use them across objects. For example, you might call that data type login
instead, and use it not just for users, but for many different objects in your database. I've found this to be a lot cleaner, and lead to easier to maintain code. (Of course, if you don't like this decision, the other validation libraries might be better for you.)
(Side note: this also encourages people to set max lengths on their data types, which is something that can be easily forgotten with other validators, and it critical for API reliability/security.)
If this is really not something you want, and you want to define things inline (which can be valid for certain use cases that have to be dynamic), you can have validation functions right in the struct definition, for example:
const User = struct({
id: 'number',
name: 'string',
username: v => typeof v === 'string' && v.length > 3 && v.length < 30 && /[a-zA-Z0-9]+/.test(v),
...
})
That way you can get custom without having to define the type up front.
As for the unique
database constraint, I wouldn't conflate that with validation, and would just let that fail at the database level personally. But check out #48 for the reason why Superstruct doesn't support async validations.
Hope that helps! I'm going to close this out as a question, but feel free to ask follow ups here if you have any other questions about this.
from superstruct.
@ianstormtaylor thank you for such a detailed answer, resolves all questions I have :)
from superstruct.
@frandiox good question, that part isn't super well documented, but if you're specifically looking to attach more information to your errors you can return failure object from the validators, not just booleans. But booleans are the 90% case.
Check out the Validator
reference, which for now is the best place to see it. It's those Failure
objects that can be returned.
from superstruct.
You custom types for that.
from superstruct.
@poltib yep, I saw this in the docs, how will you create dynamic type where you can pass arguments? For example for length rule and its value 100 or other.
from superstruct.
Hey @vladshcherbin good question, can you explain your use case for the length check? Thanks!
from superstruct.
@ianstormtaylor I was interested in using this library as a validation library, here are some of typical type checks I'll need (with ref links about what they do):
- min - to check min value
- max - to check max value
- between - to check if value is between min and max value
- before - to check date
- other dynamic types where you need to pass arguments
from superstruct.
There are similar rules (or type checks) in libraries, mentioned in the docs:
from superstruct.
@vladshcherbin what specific types of data are you looking to use min/max length checks for? This library is built differently than Joi/etc. and encourages different patterns. But I'm curious to hear what your use case needs them for before I write up an explanation assuming things.
from superstruct.
@ianstormtaylor I'd like to start at least with basic ones, strings and numbers - min/max/between for them.
from superstruct.
Another rule I use everywhere is unique
where I can pass the database table name and column so I can use them to check value dynamically. Something like this: unique('articles', 'title')
. I'm interested in this one too.
// looks something like this I guess
const articlesStruct = struct({
title: struct.intersection(['string', 'alphaNum', max(30), unique('articles', 'title')])
})
from superstruct.
@ianstormtaylor In love with Superstruct, but struggling a bit with this. How would you go about returning proper errors with this kind of validation? Something like "Value exceeds 80 characters". If we use a function that just returns false
when any of the internal checks fail, then I don't know how create an error message.
from superstruct.
Related Issues (20)
- Example coercion does not work. Have I done it right ? HOT 2
- [Question|Feature] Add functions to an interface
- [Feature] Support for `Required` HOT 1
- Please provide security reporting information or enable advisories
- `intersection` flattens unions too much HOT 1
- [Feature] `one of` or `or` type HOT 2
- [Feature] Discriminated unions (fast lookup) HOT 1
- `size` on `array` uses a permissive type
- Defaulted optional to undefined does not fill field with default value
- Never type creates a typescript issue
- Dynamic context property access
- Unexpected behaviour when combining `assign` + `refine`
- pattern (regex) does not return consistent output when using the global modifier
- Source maps seem broken HOT 4
- `instance` causes a TypeScript error with abstract classes
- Unions of instances produce unhelpful error message
- Fix compatibility with Node16/NodeNext moduleResolution HOT 4
- Mask fails on `interface aaa { foo: string; [key: string]: any }` interface with any key.
- Move tests to Vitest
- Describe does not work well with union types
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from superstruct.