Alex Alex - 1 year ago 83
Javascript Question

SimpleSchema match any type but null

I'm planning to make a collection to hold different app-wide settings, like, say, amount of logged in users today, Google analytics tracking ID, etc. So I made a schema like this:

options_schema = new SimpleSchema({
key: {
type: String,
unique: true
value: {
modified: {
type: Date

Now the main problem is that I want
to be of any type: Number, String, Date, or even custom Objects. Though it has to be present, can't be

But of course it gets angry about not specifying the type. Is there a workaround for this?


You can use Match patterns for your fields' type which allow you to do pretty much anything :

const notNullPattern = Match.Where(val => val !== null)
value : {
  type : notNullPattern

(See Arrow functions)

Note that this will allow everything but null, including undefined.
Defining patterns this way allow you to use them everywhere in your application including in check :

  key : 'the key',
  modified :,
  value : {} // or [], 42, false, 'hello ground', ...
}, optionsSchema)
Match.test(undefined, notNullPattern) //true
Match.test({}, notNullPattern) //true
Match.test(null, notNullPattern) //false

A more general solution to exclude one value would simply be:

const notValuePattern =
  unwantedValue => Match.Where(val => val !== unwantedValue))

The use of which is similar to the above:

Match.test(42, notValuePattern(null)) // true

Note that due to the use of the identity operator === it will notably fail for NaN:

Match.test(NaN, notValuePattern(NaN)) // true :(

A solution could be:

const notValuePattern =
  unwantedValue => Match.Where(val => Number.isNaN(unwantedValue)?
    : val !== unwantedValue

Should you want a solution to exclude some specific values in a schema (kind of the contrary of Match.OneOf), you could use the following:

const notOneOfPattern = (...unwantedValues) => 
  Match.Where(val => !unwantedValues.includes(val)

This uses Array.prototype.includes and the ... spread operator. Use as follow:

Match.test(42, notOneOfPattern('self-conscious whale', 43)) // true
Match.test('tuna', notOneOfPattern('tyranny', 'tuna')) // false
Match.test('evil', notOneOfPattern('Plop', 'kittens')) // true

const disallowedValues = ['coffee', 'unicorns', 'bug-free software']
Match.test('bad thing', notOneOfPattern(...disallowedValues)) // true