From 3a543656d6862ef4bc9eead582f1783d41b8bfc6 Mon Sep 17 00:00:00 2001 From: sinclairzx81 Date: Wed, 2 Aug 2023 19:59:39 +0900 Subject: [PATCH] Intrinsic String Mapping (#517) --- package-lock.json | 4 ++-- package.json | 2 +- src/typebox.ts | 4 ++-- test/runtime/type/guard/capitalize.ts | 5 +++++ test/runtime/type/guard/lowercase.ts | 5 +++++ test/runtime/type/guard/uncapitalize.ts | 5 +++++ test/runtime/type/guard/uppercase.ts | 5 +++++ test/runtime/type/intrinsic/intrinsic.ts | 23 +++++++++++++++++++++++ test/static/capitalize.ts | 3 +++ test/static/lowercase.ts | 3 +++ test/static/uncapitalize.ts | 3 +++ test/static/uppercase.ts | 3 +++ 12 files changed, 60 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 96f1ad9..3c774d7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@sinclair/typebox", - "version": "0.30.1", + "version": "0.30.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@sinclair/typebox", - "version": "0.30.1", + "version": "0.30.2", "license": "MIT", "devDependencies": { "@sinclair/hammer": "^0.17.1", diff --git a/package.json b/package.json index bd16d71..e2e0cb9 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/typebox.ts b/src/typebox.ts index 8211fec..8f37e24 100644 --- a/src/typebox.ts +++ b/src/typebox.ts @@ -434,7 +434,7 @@ export type TIntrinsicLiteral = M extends 'Uppercase' ? Uppercase : M extends 'Lowercase' ? Lowercase : string - : '' + : T // prettier-ignore export type TIntrinsicRest = T extends [infer L, ...infer R] ? [TIntrinsic, M>, ...TIntrinsicRest, M>] @@ -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 [] diff --git a/test/runtime/type/guard/capitalize.ts b/test/runtime/type/guard/capitalize.ts index 77720f4..33ed2e9 100644 --- a/test/runtime/type/guard/capitalize.ts +++ b/test/runtime/type/guard/capitalize.ts @@ -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)$') + }) }) diff --git a/test/runtime/type/guard/lowercase.ts b/test/runtime/type/guard/lowercase.ts index 7eaecf9..5a07e5d 100644 --- a/test/runtime/type/guard/lowercase.ts +++ b/test/runtime/type/guard/lowercase.ts @@ -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)$') + }) }) diff --git a/test/runtime/type/guard/uncapitalize.ts b/test/runtime/type/guard/uncapitalize.ts index a0fbd88..d54b4e5 100644 --- a/test/runtime/type/guard/uncapitalize.ts +++ b/test/runtime/type/guard/uncapitalize.ts @@ -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)$') + }) }) diff --git a/test/runtime/type/guard/uppercase.ts b/test/runtime/type/guard/uppercase.ts index 241ead7..602ddf4 100644 --- a/test/runtime/type/guard/uppercase.ts +++ b/test/runtime/type/guard/uppercase.ts @@ -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)$') + }) }) diff --git a/test/runtime/type/intrinsic/intrinsic.ts b/test/runtime/type/intrinsic/intrinsic.ts index 074223c..966f0df 100644 --- a/test/runtime/type/intrinsic/intrinsic.ts +++ b/test/runtime/type/intrinsic/intrinsic.ts @@ -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', () => { diff --git a/test/static/capitalize.ts b/test/static/capitalize.ts index 8260752..ca02c73 100644 --- a/test/static/capitalize.ts +++ b/test/static/capitalize.ts @@ -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 }>() diff --git a/test/static/lowercase.ts b/test/static/lowercase.ts index 5a4f23c..78c7f7a 100644 --- a/test/static/lowercase.ts +++ b/test/static/lowercase.ts @@ -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 }>() diff --git a/test/static/uncapitalize.ts b/test/static/uncapitalize.ts index c44caa5..a52d0c0 100644 --- a/test/static/uncapitalize.ts +++ b/test/static/uncapitalize.ts @@ -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 }>() diff --git a/test/static/uppercase.ts b/test/static/uppercase.ts index 2c8e90c..dafde13 100644 --- a/test/static/uppercase.ts +++ b/test/static/uppercase.ts @@ -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 }>()