typebox icon indicating copy to clipboard operation
typebox copied to clipboard

Support for intrinsic string manipulation on TString

Open quentinverlhac opened this issue 2 years ago • 2 comments

Hello,

This issue is reporting what seems to me an inconsistency with TypeScript behaviour.

Since this pull request, TypeScript allows a type to represent all the strings that are Uppercase, Lowercase, Capitalize, or Uncapitalize. These types are Uppercase<string>, Lowercase<string> Capitalize<string> and Uncapitalize<string> respectively.

However it seems that typebox doesn't support this feature. Applying an intrinsic type on a string type gives a TString type, which is then inferred into string type instead of following the TypeScript behaviour.

For example:

const LowercaseStringSchema = Type.Lowercase(Type.String()) // LowercaseStringSchema is TString

type LowercaseStringType = Static<typeof LowercaseStringSchema> // LowercaseStringType is string

But in TypeScript:

type LowercaseString = Lowercase<string> // LowercaseString is Lowercase<string> instead of string

Would it be possible to support this feature when inferring the static type of a schema? Maybe there is a good reason not to support this feature and I missed it, apologies if this is the case.

Thank you for supporting this package!

quentinverlhac avatar Dec 11 '23 19:12 quentinverlhac

@quentinverlhac Hi,

Thanks for the suggestion, I think this is a good idea. Currently intrinsic string manipulation types are only supported for remapping finite literal/template literal values, with the intrinsic applying an immediate remap of the type.

const T = Type.Uppercase(Type.Literal('hello')) // T: TLiteral<'HELLO'>

Where above the return value is evaluated immediately to be { const: 'HELLO' } (which is meaningful to Json Schema). However I can imagine scenarios like the following.

const T = Type.Object({
  value: Type.Uppercase(Type.String()) // only allow strings that are uppercase
})

In which case the schema would be { type: 'string', pattern: '^[A-Z]*$' }, and where TypeBox would need to represent that to the type system as TUppercase<T> such that it can be correctly composed with other types, such as TemplateLiteral.

I will do a review of what would be required to make it work once 0.32.0 is published. Unfortunately, I don't expect this functionality to land soon (as I expect implementing this correctly would involve updating a quite a few existing types to ensure they map correctly), but will try pick it up early to mid next year.

Thanks for the suggestion! S

sinclairzx81 avatar Dec 12 '23 02:12 sinclairzx81

Hi @sinclairzx81, Thanks for considering this suggestion. Using regex in the JSON schema would be very useful as well. I'm looking forward to seeing it implemented!

quentinverlhac avatar Dec 12 '23 11:12 quentinverlhac