Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

accept regex for pattern option #615

Closed
boywithkeyboard opened this issue Oct 3, 2023 · 5 comments
Closed

accept regex for pattern option #615

boywithkeyboard opened this issue Oct 3, 2023 · 5 comments

Comments

@boywithkeyboard
Copy link

boywithkeyboard commented Oct 3, 2023

It'd be awesome if TypeBox would accept a regular expression for the pattern option:

Type.String({
  pattern: /example/
})

The regular expression could internally be converted to a string:

regex.toString()
@sinclairzx81
Copy link
Owner

@boywithkeyboard Hi,

You can use Type.RegExp() for this (which is just an alias type for Type.String())

import { Type } from '@sinclair/typebox'

// [JavaScript] Creates a String type from a Regular Expression
//
const T = Type.RegExp(/example/)

// Which is an alias for 

const T = Type.String({ pattern: /example/.source })

Regular Expression Considerations

Unfortunately, I can't add regular expression support to Type.String() without running up against the specification (as Json Schema doesn't properly support the full ECMA262 regular expression syntax (with special note to flags (such as ignoreCasing) and Unicode support)).

It's actually questionable if the Type.RegExp() type should exist as an alias to Type.String() (given it permits more than is possible in the specification). I have been considering changing Type.RegExp() to be a distinct type unto itself just to support the full ECMA262 syntax.

For now though, implementations should try and limit to the following syntax.

https://json-schema.org/understanding-json-schema/reference/regular_expressions

Hope this helps
S

@boywithkeyboard
Copy link
Author

Alright, thanks!

@SleepWalker
Copy link

Hello @sinclairzx81, what is the correct way to use RegExp today? It generates definition: {type 'RegExp', source: '...'}. It does not return type: string anymore and it seems that this type is not supported by JSON Schema

@sinclairzx81
Copy link
Owner

@SleepWalker Hi,

RegExp was moved to [JavaScript] as a non-standard type on 0.32.0. The reason for this change was due to the ECMA 262 regular expression syntax (the one implemented in JavaScript) being above and beyond the minimal subset supported by Json Schema (the Json Schema subset is documented here), This change was made to draw a greater distinction between specification supported syntax and full expressions supported by JavaScript.

For the most part, you should be able to update the previous RegEx type to String({ pattern }), but I'll list some other string pattern options below in case they are relevant.


Pattern

Use the following if you need to publish the schematics and/or retain interoperability with Ajv and the Json Schema specification. This is approach is typically recommended and previous implementations using RegEx (pre-0.32.0) should be updated to use approach.

const T = Type.String({ pattern: '^Option(A|B|C)$' })

const T = Type.String({ pattern: /^Option(A|B|C)$/.source }) // this also works

const R = Value.Check(T, 'OptionA') // true

Template Literal

Use Template Literal if a regular expression can be encoded as a template. TypeBox will encode Template Literals as Json Schema compliant regular expressions and they also provide type inference.

const T = Type.TemplateLiteral('Option${A|B|C}')

const T = Type.TemplateLiteral([ // can also be written this way
  Type.Literal('Option'),
  Type.Union([             
    Type.Literal('A'),
    Type.Literal('B'),
    Type.Literal('C'),
  ])
])

const R = Value.Check(T, 'OptionA') // true

RegExp

Use the RegExp if you need UTF-16 support and expressions above and beyond those supported by Json Schema. This type is non-standard and only works with TypeBox's TypeCompiler or Value modules.

// emoji only expression
const T = Type.RegExp(/<a?:.+?:\d{18}>|\p{Extended_Pictographic}/gu)

const R = Value.Check(T, '♥️♦️♠️♣️') // true

Format

In cases where you need UTF-16 support and compatibility with Ajv, use string formats. Formats do require configuration. The following configures for TypeBox (information on Ajv configuration can be found here)

import { FormatRegistry } from '@sinclair/typebox'

FormatRegistry.Set('emoji', value => /<a?:.+?:\d{18}>|\p{Extended_Pictographic}/gu.test(value))

const T = Type.String({ format: 'emoji' })

const R = Value.Check(T, '♥️♦️♠️♣️') // true

Hope this helps
S

@SleepWalker
Copy link

Sorry I was insufficiently attentive reading the last changelog. I've thought there was just a new name for an old thing 😅

Thank you for the detailed explanation ❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants