Skip to content

Commit

Permalink
Intrinsic String Mapping (#517)
Browse files Browse the repository at this point in the history
  • Loading branch information
sinclairzx81 authored Aug 2, 2023
1 parent 72ffd1a commit 3a54365
Show file tree
Hide file tree
Showing 12 changed files with 60 additions and 5 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@sinclair/typebox",
"version": "0.30.1",
"version": "0.30.2",
"description": "JSONSchema Type Builder with Static Type Resolution for TypeScript",
"keywords": [
"typescript",
Expand Down
4 changes: 2 additions & 2 deletions src/typebox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ export type TIntrinsicLiteral<T, M extends TIntrinsicMode> =
M extends 'Uppercase' ? Uppercase<T> :
M extends 'Lowercase' ? Lowercase<T> :
string
: ''
: T
// prettier-ignore
export type TIntrinsicRest<T extends TSchema[], M extends TIntrinsicMode> = T extends [infer L, ...infer R]
? [TIntrinsic<AssertType<L>, M>, ...TIntrinsicRest<AssertRest<R>, M>]
Expand Down Expand Up @@ -2176,7 +2176,7 @@ export namespace Intrinsic {
mode === 'Capitalize' ? Capitalize(value) :
mode === 'Uppercase' ? Uppercase(value) :
mode === 'Lowercase' ? Lowercase(value) :
value) : ''
value) : value.toString()
}
function IntrinsicRest(schema: TSchema[], mode: TIntrinsicMode): TSchema[] {
if (schema.length === 0) return []
Expand Down
5 changes: 5 additions & 0 deletions test/runtime/type/guard/capitalize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,9 @@ describe('type/guard/Capitalize', () => {
Assert.IsTrue(TypeGuard.TTemplateLiteral(T))
Assert.IsEqual(T.pattern, '^(Hello0|Hello1)$')
})
it('Should guard for Capitalize 5', () => {
const T = Type.Capitalize(Type.TemplateLiteral([Type.Literal('hello'), Type.Union([Type.Literal(0), Type.Literal(1)])]))
Assert.IsTrue(TypeGuard.TTemplateLiteral(T))
Assert.IsEqual(T.pattern, '^(Hello0|Hello1)$')
})
})
5 changes: 5 additions & 0 deletions test/runtime/type/guard/lowercase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,9 @@ describe('type/guard/Lowercase', () => {
Assert.IsTrue(TypeGuard.TTemplateLiteral(T))
Assert.IsEqual(T.pattern, '^(hello0|hello1)$')
})
it('Should guard for Lowercase 5', () => {
const T = Type.Lowercase(Type.TemplateLiteral([Type.Literal('HELLO'), Type.Union([Type.Literal(0), Type.Literal(1)])]))
Assert.IsTrue(TypeGuard.TTemplateLiteral(T))
Assert.IsEqual(T.pattern, '^(hello0|hello1)$')
})
})
5 changes: 5 additions & 0 deletions test/runtime/type/guard/uncapitalize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,9 @@ describe('type/guard/Uncapitalize', () => {
Assert.IsTrue(TypeGuard.TTemplateLiteral(T))
Assert.IsEqual(T.pattern, '^(hELLO0|hELLO1)$')
})
it('Should guard for Uncapitalize 5', () => {
const T = Type.Uncapitalize(Type.TemplateLiteral([Type.Literal('HELLO'), Type.Union([Type.Literal(0), Type.Literal(1)])]))
Assert.IsTrue(TypeGuard.TTemplateLiteral(T))
Assert.IsEqual(T.pattern, '^(hELLO0|hELLO1)$')
})
})
5 changes: 5 additions & 0 deletions test/runtime/type/guard/uppercase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,9 @@ describe('type/guard/Uppercase', () => {
Assert.IsTrue(TypeGuard.TTemplateLiteral(T))
Assert.IsEqual(T.pattern, '^(HELLO0|HELLO1)$')
})
it('Should guard for Uppercase 5', () => {
const T = Type.Uppercase(Type.TemplateLiteral([Type.Literal('hello'), Type.Union([Type.Literal(0), Type.Literal(1)])]))
Assert.IsTrue(TypeGuard.TTemplateLiteral(T))
Assert.IsEqual(T.pattern, '^(HELLO0|HELLO1)$')
})
})
23 changes: 23 additions & 0 deletions test/runtime/type/intrinsic/intrinsic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,29 @@ describe('type/intrinsic/IntrinsicString', () => {
Assert.IsEqual(T.pattern, '^(hello1world|hello2world)$')
})
// ----------------------------------------------------
// Mode: TemplateLiteral Numeric
// ----------------------------------------------------
it('Should map template literal numeric: Capitalize', () => {
const T = Intrinsic.Map(Type.TemplateLiteral([Type.Literal('hello'), Type.Union([Type.Literal(1), Type.Literal(2)])]), 'Capitalize')
Assert.IsTrue(TypeGuard.TTemplateLiteral(T))
Assert.IsEqual(T.pattern, '^(Hello1|Hello2)$')
})
it('Should map template literal numeric: Uncapitalize', () => {
const T = Intrinsic.Map(Type.TemplateLiteral([Type.Literal('HELLO'), Type.Union([Type.Literal(1), Type.Literal(2)])]), 'Uncapitalize')
Assert.IsTrue(TypeGuard.TTemplateLiteral(T))
Assert.IsEqual(T.pattern, '^(hELLO1|hELLO2)$')
})
it('Should map template literal numeric: Uppercase', () => {
const T = Intrinsic.Map(Type.TemplateLiteral([Type.Literal('hello'), Type.Union([Type.Literal(1), Type.Literal(2)])]), 'Uppercase')
Assert.IsTrue(TypeGuard.TTemplateLiteral(T))
Assert.IsEqual(T.pattern, '^(HELLO1|HELLO2)$')
})
it('Should map template literal numeric: Lowercase', () => {
const T = Intrinsic.Map(Type.TemplateLiteral([Type.Literal('HELLO'), Type.Union([Type.Literal(1), Type.Literal(2)])]), 'Lowercase')
Assert.IsTrue(TypeGuard.TTemplateLiteral(T))
Assert.IsEqual(T.pattern, '^(hello1|hello2)$')
})
// ----------------------------------------------------
// Mode: TemplateLiteral Patterns
// ----------------------------------------------------
it('Should map template literal patterns 1', () => {
Expand Down
3 changes: 3 additions & 0 deletions test/static/capitalize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@ Expect(Type.Capitalize(Type.Union([Type.Literal('hello'), Type.Literal('world')]

Expect(Type.Capitalize(Type.TemplateLiteral('hello${0|1}'))).ToInfer<'Hello0' | 'Hello1'>()

// prettier-ignore
Expect(Type.Capitalize(Type.TemplateLiteral([Type.Literal('hello'), Type.Union([Type.Literal(1), Type.Literal(2)])]))).ToBe<'Hello1' | 'Hello2'>()

// passthrough
Expect(Type.Capitalize(Type.Object({ x: Type.Number() }))).ToInfer<{ x: number }>()
3 changes: 3 additions & 0 deletions test/static/lowercase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@ Expect(Type.Lowercase(Type.Union([Type.Literal('HELLO'), Type.Literal('WORLD')])

Expect(Type.Lowercase(Type.TemplateLiteral('HELLO${0|1}'))).ToInfer<'hello0' | 'hello1'>()

// prettier-ignore
Expect(Type.Lowercase(Type.TemplateLiteral([Type.Literal('HELLO'), Type.Union([Type.Literal(1), Type.Literal(2)])]))).ToBe<'hello1' | 'hello2'>()

// passthrough
Expect(Type.Lowercase(Type.Object({ x: Type.Number() }))).ToInfer<{ x: number }>()
3 changes: 3 additions & 0 deletions test/static/uncapitalize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@ Expect(Type.Uncapitalize(Type.Union([Type.Literal('HELLO'), Type.Literal('WORLD'

Expect(Type.Uncapitalize(Type.TemplateLiteral('HELLO${0|1}'))).ToInfer<'hELLO0' | 'hELLO1'>()

// prettier-ignore
Expect(Type.Uncapitalize(Type.TemplateLiteral([Type.Literal('HELLO'), Type.Union([Type.Literal(1), Type.Literal(2)])]))).ToBe<'hELLO1' | 'hELLO2'>()

// passthrough
Expect(Type.Uncapitalize(Type.Object({ x: Type.Number() }))).ToInfer<{ x: number }>()
3 changes: 3 additions & 0 deletions test/static/uppercase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@ Expect(Type.Uppercase(Type.Union([Type.Literal('hello'), Type.Literal('world')])

Expect(Type.Uppercase(Type.TemplateLiteral('HELLO${0|1}'))).ToInfer<'HELLO0' | 'HELLO1'>()

// prettier-ignore
Expect(Type.Uppercase(Type.TemplateLiteral([Type.Literal('hello'), Type.Union([Type.Literal(1), Type.Literal(2)])]))).ToBe<'HELLO1' | 'HELLO2'>()

// passthrough
Expect(Type.Uppercase(Type.Object({ x: Type.Number() }))).ToInfer<{ x: number }>()

0 comments on commit 3a54365

Please sign in to comment.