@@ -248,7 +248,7 @@ export interface TAsyncIterator<T extends TSchema = TSchema> extends TSchema {
248
248
items : T
249
249
}
250
250
// -------------------------------------------------------------------------------
251
- // Awaited
251
+ // TAwaited
252
252
// -------------------------------------------------------------------------------
253
253
// prettier-ignore
254
254
export type TAwaitedRest < T extends TSchema [ ] > = T extends [ infer L , ...infer R ]
@@ -394,7 +394,6 @@ export interface TFunction<T extends TSchema[] = TSchema[], U extends TSchema =
394
394
// --------------------------------------------------------------------------
395
395
// TIndex
396
396
// --------------------------------------------------------------------------
397
-
398
397
export type TIndexRest < T extends TSchema [ ] , K extends TPropertyKey > = T extends [ infer L , ...infer R ] ? [ TIndexType < AssertType < L > , K > , ...TIndexRest < AssertRest < R > , K > ] : [ ]
399
398
export type TIndexProperty < T extends TProperties , K extends TPropertyKey > = K extends keyof T ? [ T [ K ] ] : [ ]
400
399
export type TIndexTuple < T extends TSchema [ ] , K extends TPropertyKey > = K extends keyof T ? [ T [ K ] ] : [ ]
@@ -419,6 +418,34 @@ export type TIndex<T extends TSchema, K extends TPropertyKey[]> =
419
418
T extends TTuple ? UnionType < Flat < TIndexRestMany < T , K > > > :
420
419
TNever
421
420
// --------------------------------------------------------------------------
421
+ // TIntrinsic
422
+ // --------------------------------------------------------------------------
423
+ export type TIntrinsicMode = 'Uppercase' | 'Lowercase' | 'Capitalize' | 'Uncapitalize'
424
+ // prettier-ignore
425
+ export type TIntrinsicTemplateLiteral < T extends TTemplateLiteralKind [ ] , M extends TIntrinsicMode > =
426
+ M extends ( 'Lowercase' | 'Uppercase' ) ? T extends [ infer L , ...infer R ] ? [ TIntrinsic < AssertType < L > , M > , ...TIntrinsicTemplateLiteral < AssertRest < R > , M > ] : T :
427
+ M extends ( 'Capitalize' | 'Uncapitalize' ) ? T extends [ infer L , ...infer R ] ? [ TIntrinsic < AssertType < L > , M > , ...R ] : T :
428
+ T
429
+ // prettier-ignore
430
+ export type TIntrinsicLiteral < T , M extends TIntrinsicMode > =
431
+ T extends string ?
432
+ M extends 'Uncapitalize' ? Uncapitalize < T > :
433
+ M extends 'Capitalize' ? Capitalize < T > :
434
+ M extends 'Uppercase' ? Uppercase < T > :
435
+ M extends 'Lowercase' ? Lowercase < T > :
436
+ string
437
+ : ''
438
+ // prettier-ignore
439
+ export type TIntrinsicRest < T extends TSchema [ ] , M extends TIntrinsicMode > = T extends [ infer L , ...infer R ]
440
+ ? [ TIntrinsic < AssertType < L > , M > , ...TIntrinsicRest < AssertRest < R > , M > ]
441
+ : [ ]
442
+ // prettier-ignore
443
+ export type TIntrinsic < T extends TSchema , M extends TIntrinsicMode > =
444
+ T extends TTemplateLiteral < infer S > ? TTemplateLiteral < TIntrinsicTemplateLiteral < S , M > > :
445
+ T extends TUnion < infer S > ? TUnion < TIntrinsicRest < S , M > > :
446
+ T extends TLiteral < infer S > ? TLiteral < TIntrinsicLiteral < S , M > > :
447
+ T
448
+ // --------------------------------------------------------------------------
422
449
// TInteger
423
450
// --------------------------------------------------------------------------
424
451
export interface TInteger extends TSchema , NumericOptions < number > {
@@ -1306,8 +1333,15 @@ export namespace TypeGuard {
1306
1333
}
1307
1334
/** Returns true if the given schema is TString */
1308
1335
export function TString ( schema : unknown ) : schema is TString {
1336
+ // prettier-ignore
1309
1337
return (
1310
- TKindOf ( schema , 'String' ) && schema . type === 'string' && IsOptionalString ( schema . $id ) && IsOptionalNumber ( schema . minLength ) && IsOptionalNumber ( schema . maxLength ) && IsOptionalPattern ( schema . pattern ) && IsOptionalFormat ( schema . format )
1338
+ TKindOf ( schema , 'String' ) &&
1339
+ schema . type === 'string' &&
1340
+ IsOptionalString ( schema . $id ) &&
1341
+ IsOptionalNumber ( schema . minLength ) &&
1342
+ IsOptionalNumber ( schema . maxLength ) &&
1343
+ IsOptionalPattern ( schema . pattern ) &&
1344
+ IsOptionalFormat ( schema . format )
1311
1345
)
1312
1346
}
1313
1347
/** Returns true if the given schema is TSymbol */
@@ -2106,6 +2140,61 @@ export namespace IndexedAccessor {
2106
2140
}
2107
2141
}
2108
2142
// --------------------------------------------------------------------------
2143
+ // Intrinsic
2144
+ // --------------------------------------------------------------------------
2145
+ export namespace Intrinsic {
2146
+ function Uncapitalize ( value : string ) : string {
2147
+ const [ first , rest ] = [ value . slice ( 0 , 1 ) , value . slice ( 1 ) ]
2148
+ return `${ first . toLowerCase ( ) } ${ rest } `
2149
+ }
2150
+ function Capitalize ( value : string ) : string {
2151
+ const [ first , rest ] = [ value . slice ( 0 , 1 ) , value . slice ( 1 ) ]
2152
+ return `${ first . toUpperCase ( ) } ${ rest } `
2153
+ }
2154
+ function Uppercase ( value : string ) : string {
2155
+ return value . toUpperCase ( )
2156
+ }
2157
+ function Lowercase ( value : string ) : string {
2158
+ return value . toLowerCase ( )
2159
+ }
2160
+ function IntrinsicTemplateLiteral ( schema : TTemplateLiteral , mode : TIntrinsicMode ) {
2161
+ // note: template literals require special runtime handling as they are encoded in string patterns.
2162
+ // This diverges from the mapped type which would otherwise map on the template literal kind.
2163
+ const expression = TemplateLiteralParser . ParseExact ( schema . pattern )
2164
+ const finite = TemplateLiteralFinite . Check ( expression )
2165
+ if ( ! finite ) return { ...schema , pattern : IntrinsicLiteral ( schema . pattern , mode ) } as any
2166
+ const strings = [ ...TemplateLiteralGenerator . Generate ( expression ) ]
2167
+ const literals = strings . map ( ( value ) => Type . Literal ( value ) )
2168
+ const mapped = IntrinsicRest ( literals as any , mode )
2169
+ const union = Type . Union ( mapped )
2170
+ return Type . TemplateLiteral ( [ union ] )
2171
+ }
2172
+ function IntrinsicLiteral ( value : TLiteralValue , mode : TIntrinsicMode ) {
2173
+ // prettier-ignore
2174
+ return typeof value === 'string' ? (
2175
+ mode === 'Uncapitalize' ? Uncapitalize ( value ) :
2176
+ mode === 'Capitalize' ? Capitalize ( value ) :
2177
+ mode === 'Uppercase' ? Uppercase ( value ) :
2178
+ mode === 'Lowercase' ? Lowercase ( value ) :
2179
+ value ) : ''
2180
+ }
2181
+ function IntrinsicRest ( schema : TSchema [ ] , mode : TIntrinsicMode ) : TSchema [ ] {
2182
+ if ( schema . length === 0 ) return [ ]
2183
+ const [ L , ...R ] = schema
2184
+ return [ Map ( L , mode ) , ...IntrinsicRest ( R , mode ) ]
2185
+ }
2186
+ function Visit ( schema : TSchema , mode : TIntrinsicMode ) {
2187
+ if ( TypeGuard . TTemplateLiteral ( schema ) ) return IntrinsicTemplateLiteral ( schema , mode )
2188
+ if ( TypeGuard . TUnion ( schema ) ) return Type . Union ( IntrinsicRest ( schema . anyOf , mode ) )
2189
+ if ( TypeGuard . TLiteral ( schema ) ) return Type . Literal ( IntrinsicLiteral ( schema . const , mode ) )
2190
+ return schema
2191
+ }
2192
+ /** Applies an intrinsic string manipulation to the given type. */
2193
+ export function Map < T extends TSchema , M extends TIntrinsicMode > ( schema : T , mode : M ) : TIntrinsic < T , M > {
2194
+ return Visit ( schema , mode )
2195
+ }
2196
+ }
2197
+ // --------------------------------------------------------------------------
2109
2198
// ObjectMap
2110
2199
// --------------------------------------------------------------------------
2111
2200
export namespace ObjectMap {
@@ -2538,10 +2627,9 @@ export class StandardTypeBuilder extends TypeBuilder {
2538
2627
public Boolean ( options : SchemaOptions = { } ) : TBoolean {
2539
2628
return this . Create ( { ...options , [ Kind ] : 'Boolean' , type : 'boolean' } )
2540
2629
}
2541
- /** `[Standard]` Capitalize a LiteralString type */
2542
- public Capitalize < T extends TLiteral < string > > ( schema : T , options : SchemaOptions = { } ) : TLiteral < Capitalize < T [ 'const' ] > > {
2543
- const [ first , rest ] = [ schema . const . slice ( 0 , 1 ) , schema . const . slice ( 1 ) ]
2544
- return Type . Literal ( `${ first . toUpperCase ( ) } ${ rest } ` as Capitalize < T [ 'const' ] > , options )
2630
+ /** `[Standard]` Intrinsic function to Capitalize LiteralString types */
2631
+ public Capitalize < T extends TSchema > ( schema : T , options : SchemaOptions = { } ) : TIntrinsic < T , 'Capitalize' > {
2632
+ return { ...Intrinsic . Map ( TypeClone . Clone ( schema ) , 'Capitalize' ) , ...options }
2545
2633
}
2546
2634
/** `[Standard]` Creates a Composite object type */
2547
2635
public Composite < T extends TObject [ ] > ( objects : [ ...T ] , options ?: ObjectOptions ) : TComposite < T > {
@@ -2665,9 +2753,9 @@ export class StandardTypeBuilder extends TypeBuilder {
2665
2753
public Literal < T extends TLiteralValue > ( value : T , options : SchemaOptions = { } ) : TLiteral < T > {
2666
2754
return this . Create ( { ...options , [ Kind ] : 'Literal' , const : value , type : typeof value as 'string' | 'number' | 'boolean' } )
2667
2755
}
2668
- /** `[Standard]` Lowercase a LiteralString type */
2669
- public Lowercase < T extends TLiteral < string > > ( schema : T , options : SchemaOptions = { } ) : TLiteral < Lowercase < T [ 'const' ] > > {
2670
- return Type . Literal ( schema . const . toLowerCase ( ) as Lowercase < T [ 'const' ] > , options )
2756
+ /** `[Standard]` Intrinsic function to Lowercase LiteralString types */
2757
+ public Lowercase < T extends TSchema > ( schema : T , options : SchemaOptions = { } ) : TIntrinsic < T , 'Lowercase' > {
2758
+ return { ... Intrinsic . Map ( TypeClone . Clone ( schema ) , ' Lowercase' ) , ... options }
2671
2759
}
2672
2760
/** `[Standard]` Creates a Never type */
2673
2761
public Never ( options : SchemaOptions = { } ) : TNever {
@@ -2857,10 +2945,9 @@ export class StandardTypeBuilder extends TypeBuilder {
2857
2945
{ ...options , [ Kind ] : 'Tuple' , type : 'array' , minItems, maxItems } ) as any
2858
2946
return this . Create ( schema )
2859
2947
}
2860
- /** `[Standard]` Uncapitalize a LiteralString type */
2861
- public Uncapitalize < T extends TLiteral < string > > ( schema : T , options : SchemaOptions = { } ) : TLiteral < Uncapitalize < T [ 'const' ] > > {
2862
- const [ first , rest ] = [ schema . const . slice ( 0 , 1 ) , schema . const . slice ( 1 ) ]
2863
- return Type . Literal ( `${ first . toLocaleLowerCase ( ) } ${ rest } ` as Uncapitalize < T [ 'const' ] > , options )
2948
+ /** `[Standard]` Intrinsic function to Uncapitalize LiteralString types */
2949
+ public Uncapitalize < T extends TSchema > ( schema : T , options : SchemaOptions = { } ) : TIntrinsic < T , 'Uncapitalize' > {
2950
+ return { ...Intrinsic . Map ( TypeClone . Clone ( schema ) , 'Uncapitalize' ) , ...options }
2864
2951
}
2865
2952
/** `[Standard]` Creates a Union type */
2866
2953
public Union ( anyOf : [ ] , options ?: SchemaOptions ) : TNever
@@ -2890,9 +2977,9 @@ export class StandardTypeBuilder extends TypeBuilder {
2890
2977
public Unsafe < T > ( options : UnsafeOptions = { } ) : TUnsafe < T > {
2891
2978
return this . Create ( { ...options , [ Kind ] : options [ Kind ] || 'Unsafe' } )
2892
2979
}
2893
- /** `[Standard]` Uppercase a LiteralString type */
2894
- public Uppercase < T extends TLiteral < string > > ( schema : T , options : SchemaOptions = { } ) : TLiteral < Uppercase < T [ 'const' ] > > {
2895
- return Type . Literal ( schema . const . toUpperCase ( ) as Uppercase < T [ 'const' ] > , options )
2980
+ /** `[Standard]` Intrinsic function to Uppercase LiteralString types */
2981
+ public Uppercase < T extends TSchema > ( schema : T , options : SchemaOptions = { } ) : TIntrinsic < T , 'Uppercase' > {
2982
+ return { ... Intrinsic . Map ( TypeClone . Clone ( schema ) , ' Uppercase' ) , ... options }
2896
2983
}
2897
2984
}
2898
2985
// --------------------------------------------------------------------------
0 commit comments