From 5278ba6f5607009ebb2a02c459deb2114c20bd37 Mon Sep 17 00:00:00 2001 From: Puppo Date: Wed, 6 May 2026 17:29:16 +0000 Subject: [PATCH 1/7] chore: migrate from tsd to tstyche - Replace tsd dependency with tstyche - Create tsconfig.json with node16 module resolution - Rename type test file from .test-d.ts to .tst.ts - Add explicit tstyche type assertions --- package.json | 4 +- tsconfig.json | 10 +++++ ...hema.test-d.ts => FluentJSONSchema.tst.ts} | 42 +++---------------- 3 files changed, 18 insertions(+), 38 deletions(-) create mode 100644 tsconfig.json rename types/{FluentJSONSchema.test-d.ts => FluentJSONSchema.tst.ts} (75%) diff --git a/package.json b/package.json index e25f3f0..07c8274 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "lint:fix": "eslint --fix", "test": "npm run test:unit && npm run test:typescript", "test:unit": "c8 --100 node --test", - "test:typescript": "tsd", + "test:typescript": "tstyche", "doc": "jsdoc2md ./src/*.js > docs/API.md" }, "devDependencies": { @@ -53,7 +53,7 @@ "jsdoc-to-markdown": "^9.0.0", "lodash.merge": "^4.6.2", "neostandard": "^0.13.0", - "tsd": "^0.33.0" + "tstyche": "^1.0.0" }, "dependencies": { "@fastify/deepmerge": "^3.0.0" diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..a38676d --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "module": "node16", + "moduleResolution": "node16", + "noEmit": true, + "strict": true, + "types": ["tstyche"] + }, + "include": ["types/**/*.ts"] +} diff --git a/types/FluentJSONSchema.test-d.ts b/types/FluentJSONSchema.tst.ts similarity index 75% rename from types/FluentJSONSchema.test-d.ts rename to types/FluentJSONSchema.tst.ts index e105b88..52f0504 100644 --- a/types/FluentJSONSchema.test-d.ts +++ b/types/FluentJSONSchema.tst.ts @@ -1,8 +1,11 @@ -// This file will be passed to the TypeScript CLI to verify our typings compile +import { expect } from 'tstyche' import S, { FluentSchemaError } from '..' -console.log('isFluentSchema:', S.object().isFluentJSONSchema) +// isFluentJSONSchema and isFluentSchema properties +expect(S.object().isFluentJSONSchema).type.toEqual() +expect(S.object().isFluentSchema).type.toEqual() + const schema = S.object() .id('http://foo.com/user') .title('A User') @@ -48,9 +51,6 @@ const schema = S.object() .writeOnly(true) .valueOf() -console.log('example:\n', JSON.stringify(schema)) -console.log('isFluentSchema:', S.object().isFluentSchema) - const userBaseSchema = S.object() .additionalProperties(false) .prop('username', S.string()) @@ -62,8 +62,6 @@ const userSchema = S.object() .prop('updatedAt', S.string().format('time')) .extend(userBaseSchema) -console.log('user:\n', JSON.stringify(userSchema.valueOf())) - const largeUserSchema = S.object() .prop('id', S.string().format('uuid')) .prop('username', S.string()) @@ -73,8 +71,6 @@ const largeUserSchema = S.object() const userSubsetSchema = largeUserSchema.only(['username', 'password']) -console.log('user subset:', JSON.stringify(userSubsetSchema.valueOf())) - const personSchema = S.object() .prop('name', S.string()) .prop('age', S.number()) @@ -84,8 +80,6 @@ const personSchema = S.object() const bodySchema = personSchema.without(['createdAt', 'updatedAt']) -console.log('person subset:', JSON.stringify(bodySchema.valueOf())) - const personSchemaAllowsUnix = S.object() .prop('name', S.string()) .prop('age', S.number()) @@ -93,32 +87,24 @@ const personSchemaAllowsUnix = S.object() .prop('createdAt', S.mixed(['string', 'integer']).format('time')) .prop('updatedAt', S.mixed(['string', 'integer']).minimum(0)) -console.log('person schema allows unix:', JSON.stringify(personSchemaAllowsUnix.valueOf())) - try { S.object().prop('foo', 'boom!' as any) } catch (e) { if (e instanceof FluentSchemaError) { - console.log(e.message) + expect(e).type.toEqual() } } const arrayExtendedSchema = S.array().items(userSchema).valueOf() -console.log('array of user\n', JSON.stringify(arrayExtendedSchema)) - const extendExtendedSchema = S.object().extend(userSchema) -console.log('extend of user\n', JSON.stringify(extendExtendedSchema)) - const rawNullableSchema = S.object() .raw({ nullable: true }) .required(['foo', 'hello']) .prop('foo', S.string()) .prop('hello', S.string()) -console.log('raw schema with nullable props\n', JSON.stringify(rawNullableSchema)) - const dependentRequired = S.object() .dependentRequired({ foo: ['bar'], @@ -127,8 +113,6 @@ const dependentRequired = S.object() .prop('bar') .valueOf() -console.log('dependentRequired:\n', JSON.stringify(dependentRequired)) - const dependentSchemas = S.object() .dependentSchemas({ foo: S.object().prop('bar'), @@ -136,15 +120,11 @@ const dependentSchemas = S.object() .prop('bar', S.object().prop('bar')) .valueOf() -console.log('dependentRequired:\n', JSON.stringify(dependentSchemas)) - const deprecatedSchema = S.object() .deprecated() .prop('foo', S.string().deprecated()) .valueOf() -console.log('deprecatedSchema:\n', JSON.stringify(deprecatedSchema)) - type Foo = { foo: string bar: string @@ -158,8 +138,6 @@ const dependentRequiredWithType = S.object() .prop('bar') .valueOf() -console.log('dependentRequired:\n', JSON.stringify(dependentRequiredWithType)) - const dependentSchemasWithType = S.object() .dependentSchemas({ foo: S.object().prop('bar'), @@ -167,15 +145,11 @@ const dependentSchemasWithType = S.object() .prop('bar', S.object().prop('bar')) .valueOf() -console.log('dependentSchemasWithType:\n', JSON.stringify(dependentSchemasWithType)) - const deprecatedSchemaWithType = S.object() .deprecated() .prop('foo', S.string().deprecated()) .valueOf() -console.log('deprecatedSchemaWithType:\n', JSON.stringify(deprecatedSchemaWithType)) - type ReallyLongType = { foo: string bar: string @@ -196,11 +170,7 @@ const deepTestOnTypes = S.object() .definition('abcd', S.number()) .valueOf() -console.log('deepTestOnTypes:\n', JSON.stringify(deepTestOnTypes)) - const tsIsoSchema = S.object() .prop('createdAt', S.string().format('iso-time')) .prop('updatedAt', S.string().format('iso-date-time')) .valueOf() - -console.log('ISO schema OK:', JSON.stringify(tsIsoSchema)) From 612ea07ebb8bf53abd7da2071f510954827023a3 Mon Sep 17 00:00:00 2001 From: Puppo Date: Wed, 6 May 2026 17:44:30 +0000 Subject: [PATCH 2/7] test: improve type assertions with comprehensive coverage - Add 82 type assertions covering all schema types - Test BaseSchema properties: id, title, description, required, isFluentSchema, etc. - Test StringSchema methods: minLength, maxLength, format, pattern, etc. - Test NumberSchema/IntegerSchema methods: minimum, maximum, multipleOf, etc. - Test ArraySchema methods: items, contains, uniqueItems, minItems, etc. - Test ObjectSchema methods: prop, definition, extend, only, without, etc. - Test FORMATS enum values - Test FluentSchemaError type - Test MixedSchema combined types --- types/FluentJSONSchema.tst.ts | 338 ++++++++++++++++++---------------- 1 file changed, 181 insertions(+), 157 deletions(-) diff --git a/types/FluentJSONSchema.tst.ts b/types/FluentJSONSchema.tst.ts index 52f0504..57721ec 100644 --- a/types/FluentJSONSchema.tst.ts +++ b/types/FluentJSONSchema.tst.ts @@ -1,176 +1,200 @@ import { expect } from 'tstyche' -import S, { FluentSchemaError } from '..' +import S, { FluentSchemaError, StringSchema, NumberSchema, ArraySchema, IntegerSchema, BooleanSchema, NullSchema } from '..' -// isFluentJSONSchema and isFluentSchema properties +// ============================================================ +// Core isFluentSchema property assertions +// ============================================================ expect(S.object().isFluentJSONSchema).type.toEqual() expect(S.object().isFluentSchema).type.toEqual() -const schema = S.object() - .id('http://foo.com/user') - .title('A User') - .description('A User desc') - .definition( - 'address', - S.object() - .id('#address') - .prop('line1', S.anyOf([S.string(), S.null()])) // JSON Schema nullable - .prop('line2', S.string().raw({ nullable: true })) // Open API / Swagger nullable - .prop('country') - .allOf([S.string()]) - .prop('city') - .prop('zipcode') - ) - .prop('username', S.string().pattern(/[a-z]*/g)) - .prop('email', S.string().format('email')) - .prop('email2', S.string().format(S.FORMATS.EMAIL)) - .prop( - 'avatar', - S.string().contentEncoding('base64').contentMediaType('image/png') - ) - .required() - .prop( - 'password', - S.string().default('123456').minLength(6).maxLength(12).pattern('.*') - ) - .required() - .prop('addresses', S.array().items([S.ref('#address')])) - .required() - .prop( - 'role', - S.object() - .id('http://foo.com/role') - .prop('name') - .enum(['ADMIN', 'USER']) - .prop('permissions') - ) - .required() - .prop('age', S.mixed(['string', 'integer'])) - .ifThen(S.object().prop('age', S.string()), S.required(['age'])) - .readOnly() - .writeOnly(true) - .valueOf() - -const userBaseSchema = S.object() - .additionalProperties(false) - .prop('username', S.string()) - .prop('password', S.string()) +// ============================================================ +// BaseSchema properties on ObjectSchema +// ============================================================ +expect(S.object()).type.toHaveProperty('id') +expect(S.object()).type.toHaveProperty('title') +expect(S.object()).type.toHaveProperty('description') +expect(S.object()).type.toHaveProperty('required') +expect(S.object()).type.toHaveProperty('isFluentSchema') +expect(S.object()).type.toHaveProperty('isFluentJSONSchema') +expect(S.object()).type.toHaveProperty('allOf') +expect(S.object()).type.toHaveProperty('anyOf') +expect(S.object()).type.toHaveProperty('oneOf') +expect(S.object()).type.toHaveProperty('not') + +// ============================================================ +// StringSchema method chains +// ============================================================ +expect(S.string().minLength(1)).type.toHaveProperty('minLength') +expect(S.string().maxLength(10)).type.toHaveProperty('maxLength') +expect(S.string().format('email')).type.toHaveProperty('format') +expect(S.string().pattern(/^\w+$/)).type.toHaveProperty('pattern') +expect(S.string().contentEncoding('base64')).type.toHaveProperty('contentEncoding') +expect(S.string().contentMediaType('image/png')).type.toHaveProperty('contentMediaType') +expect(S.string().default('default')).type.toHaveProperty('default') +expect(S.string().deprecated()).type.toHaveProperty('deprecated') + +// ============================================================ +// StringSchema return type +// ============================================================ +expect(S.string().minLength(1)).type.toEqual() +expect(S.string().format('email')).type.toEqual() +expect(S.string().pattern(/^\w+$/)).type.toEqual() +expect(S.string().contentEncoding('base64')).type.toEqual() +expect(S.string().deprecated()).type.toEqual() + +// ============================================================ +// NumberSchema method chains +// ============================================================ +expect(S.number().minimum(0)).type.toHaveProperty('minimum') +expect(S.number().maximum(100)).type.toHaveProperty('maximum') +expect(S.number().exclusiveMinimum(0)).type.toHaveProperty('exclusiveMinimum') +expect(S.number().exclusiveMaximum(100)).type.toHaveProperty('exclusiveMaximum') +expect(S.number().multipleOf(5)).type.toHaveProperty('multipleOf') + +// ============================================================ +// NumberSchema return type +// ============================================================ +expect(S.number().minimum(0)).type.toEqual() +expect(S.number().maximum(100)).type.toEqual() +expect(S.number().multipleOf(5)).type.toEqual() + +// ============================================================ +// IntegerSchema method chains +// ============================================================ +expect(S.integer().minimum(0)).type.toHaveProperty('minimum') +expect(S.integer().maximum(100)).type.toHaveProperty('maximum') +expect(S.integer().multipleOf(2)).type.toHaveProperty('multipleOf') + +// ============================================================ +// IntegerSchema return type +// ============================================================ +expect(S.integer().minimum(0)).type.toEqual() +expect(S.integer().multipleOf(2)).type.toEqual() + +// ============================================================ +// BooleanSchema +// ============================================================ +expect(S.boolean()).type.toHaveProperty('boolean') +expect(S.boolean()).type.toEqual() + +// ============================================================ +// NullSchema +// ============================================================ +expect(S.null()).type.toHaveProperty('null') +expect(S.null()).type.toEqual() + +// ============================================================ +// ArraySchema method chains +// ============================================================ +expect(S.array().items(S.string())).type.toHaveProperty('items') +expect(S.array().additionalItems(true)).type.toHaveProperty('additionalItems') +expect(S.array().contains(S.string())).type.toHaveProperty('contains') +expect(S.array().uniqueItems(true)).type.toHaveProperty('uniqueItems') +expect(S.array().minItems(1)).type.toHaveProperty('minItems') +expect(S.array().maxItems(10)).type.toHaveProperty('maxItems') + +// ============================================================ +// ArraySchema return type +// ============================================================ +expect(S.array().items(S.string())).type.toEqual() +expect(S.array().uniqueItems(true)).type.toEqual() + +// ============================================================ +// ObjectSchema method chains +// ============================================================ +expect(S.object().prop('foo', S.string())).type.toHaveProperty('prop') +expect(S.object().definition('bar', S.number())).type.toHaveProperty('definition') +expect(S.object().additionalProperties(false)).type.toHaveProperty('additionalProperties') +expect(S.object().extend(S.object())).type.toHaveProperty('extend') +expect(S.object().only(['foo'])).type.toHaveProperty('only') +expect(S.object().without(['foo'])).type.toHaveProperty('without') +expect(S.object().dependentRequired({ foo: ['bar'] })).type.toHaveProperty('dependentRequired') +expect(S.object().dependentSchemas({ foo: S.object().prop('bar') })).type.toHaveProperty('dependentSchemas') +expect(S.object().maxProperties(10)).type.toHaveProperty('maxProperties') +expect(S.object().minProperties(1)).type.toHaveProperty('minProperties') + +// ============================================================ +// FORMATS assertions +// ============================================================ +expect(S.FORMATS.EMAIL).type.toEqual<'email'>() +expect(S.FORMATS.UUID).type.toEqual<'uuid'>() +expect(S.FORMATS.DATE_TIME).type.toEqual<'date-time'>() +expect(S.FORMATS.ISO_TIME).type.toEqual<'iso-time'>() +expect(S.FORMATS.ISO_DATE_TIME).type.toEqual<'iso-date-time'>() +expect(S.FORMATS.TIME).type.toEqual<'time'>() +expect(S.FORMATS.DATE).type.toEqual<'date'>() +expect(S.FORMATS.URL).type.toEqual<'url'>() +expect(S.FORMATS.IPV4).type.toEqual<'ipv4'>() +expect(S.FORMATS.IPV6).type.toEqual<'ipv6'>() + +// ============================================================ +// FluentSchemaError instanceof check +// ============================================================ +try { + S.object().prop('foo', 'boom!' as any) +} catch (e) { + if (e instanceof FluentSchemaError) { + expect(e).type.toEqual() + } +} + +// ============================================================ +// MixedSchema assertions +// ============================================================ +expect(S.mixed(['string'])).type.toHaveProperty('minLength') +expect(S.mixed(['string', 'integer'])).type.toHaveProperty('minLength') +expect(S.mixed(['string', 'number'])).type.toHaveProperty('minimum') +// ============================================================ +// Complex schema building (preserves fluency) +// ============================================================ const userSchema = S.object() .prop('id', S.string().format('uuid')) - .prop('createdAt', S.string().format('time')) - .prop('updatedAt', S.string().format('time')) - .extend(userBaseSchema) + .prop('name', S.string()) + .prop('email', S.string().format('email')) + .prop('age', S.number()) -const largeUserSchema = S.object() - .prop('id', S.string().format('uuid')) - .prop('username', S.string()) - .prop('password', S.string()) - .prop('createdAt', S.string().format('time')) - .prop('updatedAt', S.string().format('time')) +expect(userSchema).type.toHaveProperty('prop') +expect(userSchema).type.toHaveProperty('isFluentSchema') -const userSubsetSchema = largeUserSchema.only(['username', 'password']) +// ============================================================ +// Extend returns ExtendedSchema type +// ============================================================ +const baseSchema = S.object().prop('createdAt', S.string()) +const extendedSchema = S.object().prop('id', S.string()).extend(baseSchema) -const personSchema = S.object() - .prop('name', S.string()) - .prop('age', S.number()) - .prop('id', S.string().format('uuid')) - .prop('createdAt', S.string().format('time')) - .prop('updatedAt', S.string().format('time')) +expect(extendedSchema).type.toHaveProperty('extend') -const bodySchema = personSchema.without(['createdAt', 'updatedAt']) +// ============================================================ +// Chained methods preserve correct types +// ============================================================ +expect(S.string().minLength(5).maxLength(10).pattern(/^\w+$/).format('email')) + .type.toEqual() -const personSchemaAllowsUnix = S.object() - .prop('name', S.string()) - .prop('age', S.number()) - .prop('id', S.string().format('uuid')) - .prop('createdAt', S.mixed(['string', 'integer']).format('time')) - .prop('updatedAt', S.mixed(['string', 'integer']).minimum(0)) +expect(S.number().minimum(0).maximum(100).multipleOf(5)) + .type.toEqual() -try { - S.object().prop('foo', 'boom!' as any) -} catch (e) { - if (e instanceof FluentSchemaError) { - expect(e).type.toEqual() - } -} +expect(S.array().items(S.string()).minItems(1).maxItems(10)) + .type.toEqual() -const arrayExtendedSchema = S.array().items(userSchema).valueOf() - -const extendExtendedSchema = S.object().extend(userSchema) - -const rawNullableSchema = S.object() - .raw({ nullable: true }) - .required(['foo', 'hello']) - .prop('foo', S.string()) - .prop('hello', S.string()) - -const dependentRequired = S.object() - .dependentRequired({ - foo: ['bar'], - }) - .prop('foo') - .prop('bar') - .valueOf() - -const dependentSchemas = S.object() - .dependentSchemas({ - foo: S.object().prop('bar'), - }) - .prop('bar', S.object().prop('bar')) - .valueOf() - -const deprecatedSchema = S.object() - .deprecated() - .prop('foo', S.string().deprecated()) - .valueOf() - -type Foo = { - foo: string - bar: string +// ============================================================ +// Type parameter propagation (generics) +// ============================================================ +type User = { + id: string + name: string + email: string } -const dependentRequiredWithType = S.object() - .dependentRequired({ - foo: ['bar'], - }) - .prop('foo') - .prop('bar') - .valueOf() - -const dependentSchemasWithType = S.object() - .dependentSchemas({ - foo: S.object().prop('bar'), - }) - .prop('bar', S.object().prop('bar')) - .valueOf() - -const deprecatedSchemaWithType = S.object() - .deprecated() - .prop('foo', S.string().deprecated()) - .valueOf() - -type ReallyLongType = { - foo: string - bar: string - baz: string - xpto: string - abcd: number - kct: { - a: string - b: number - d: null - } -} +const typedSchema = S.object() + .prop('id', S.string().format('uuid')) + .prop('name', S.string()) + .prop('email', S.string().format('email')) + +expect(typedSchema).type.toHaveProperty('prop') + +// Using only/without creates subset types +const subsetSchema = typedSchema.only(['id', 'name']) -const deepTestOnTypes = S.object() - .prop('bar', S.object().prop('bar')) - // you can provide any string, to avoid breaking changes - .prop('aaaa', S.anyOf([S.string()])) - .definition('abcd', S.number()) - .valueOf() - -const tsIsoSchema = S.object() - .prop('createdAt', S.string().format('iso-time')) - .prop('updatedAt', S.string().format('iso-date-time')) - .valueOf() +expect(subsetSchema).type.toHaveProperty('only') From fbf8a3ca3473998a485bb87e769254f38d2ea04d Mon Sep 17 00:00:00 2001 From: Puppo Date: Wed, 6 May 2026 17:48:55 +0000 Subject: [PATCH 3/7] Revert "test: improve type assertions with comprehensive coverage" This reverts commit 612ea07ebb8bf53abd7da2071f510954827023a3. --- types/FluentJSONSchema.tst.ts | 338 ++++++++++++++++------------------ 1 file changed, 157 insertions(+), 181 deletions(-) diff --git a/types/FluentJSONSchema.tst.ts b/types/FluentJSONSchema.tst.ts index 57721ec..52f0504 100644 --- a/types/FluentJSONSchema.tst.ts +++ b/types/FluentJSONSchema.tst.ts @@ -1,200 +1,176 @@ import { expect } from 'tstyche' -import S, { FluentSchemaError, StringSchema, NumberSchema, ArraySchema, IntegerSchema, BooleanSchema, NullSchema } from '..' +import S, { FluentSchemaError } from '..' -// ============================================================ -// Core isFluentSchema property assertions -// ============================================================ +// isFluentJSONSchema and isFluentSchema properties expect(S.object().isFluentJSONSchema).type.toEqual() expect(S.object().isFluentSchema).type.toEqual() -// ============================================================ -// BaseSchema properties on ObjectSchema -// ============================================================ -expect(S.object()).type.toHaveProperty('id') -expect(S.object()).type.toHaveProperty('title') -expect(S.object()).type.toHaveProperty('description') -expect(S.object()).type.toHaveProperty('required') -expect(S.object()).type.toHaveProperty('isFluentSchema') -expect(S.object()).type.toHaveProperty('isFluentJSONSchema') -expect(S.object()).type.toHaveProperty('allOf') -expect(S.object()).type.toHaveProperty('anyOf') -expect(S.object()).type.toHaveProperty('oneOf') -expect(S.object()).type.toHaveProperty('not') - -// ============================================================ -// StringSchema method chains -// ============================================================ -expect(S.string().minLength(1)).type.toHaveProperty('minLength') -expect(S.string().maxLength(10)).type.toHaveProperty('maxLength') -expect(S.string().format('email')).type.toHaveProperty('format') -expect(S.string().pattern(/^\w+$/)).type.toHaveProperty('pattern') -expect(S.string().contentEncoding('base64')).type.toHaveProperty('contentEncoding') -expect(S.string().contentMediaType('image/png')).type.toHaveProperty('contentMediaType') -expect(S.string().default('default')).type.toHaveProperty('default') -expect(S.string().deprecated()).type.toHaveProperty('deprecated') - -// ============================================================ -// StringSchema return type -// ============================================================ -expect(S.string().minLength(1)).type.toEqual() -expect(S.string().format('email')).type.toEqual() -expect(S.string().pattern(/^\w+$/)).type.toEqual() -expect(S.string().contentEncoding('base64')).type.toEqual() -expect(S.string().deprecated()).type.toEqual() - -// ============================================================ -// NumberSchema method chains -// ============================================================ -expect(S.number().minimum(0)).type.toHaveProperty('minimum') -expect(S.number().maximum(100)).type.toHaveProperty('maximum') -expect(S.number().exclusiveMinimum(0)).type.toHaveProperty('exclusiveMinimum') -expect(S.number().exclusiveMaximum(100)).type.toHaveProperty('exclusiveMaximum') -expect(S.number().multipleOf(5)).type.toHaveProperty('multipleOf') - -// ============================================================ -// NumberSchema return type -// ============================================================ -expect(S.number().minimum(0)).type.toEqual() -expect(S.number().maximum(100)).type.toEqual() -expect(S.number().multipleOf(5)).type.toEqual() - -// ============================================================ -// IntegerSchema method chains -// ============================================================ -expect(S.integer().minimum(0)).type.toHaveProperty('minimum') -expect(S.integer().maximum(100)).type.toHaveProperty('maximum') -expect(S.integer().multipleOf(2)).type.toHaveProperty('multipleOf') - -// ============================================================ -// IntegerSchema return type -// ============================================================ -expect(S.integer().minimum(0)).type.toEqual() -expect(S.integer().multipleOf(2)).type.toEqual() - -// ============================================================ -// BooleanSchema -// ============================================================ -expect(S.boolean()).type.toHaveProperty('boolean') -expect(S.boolean()).type.toEqual() - -// ============================================================ -// NullSchema -// ============================================================ -expect(S.null()).type.toHaveProperty('null') -expect(S.null()).type.toEqual() - -// ============================================================ -// ArraySchema method chains -// ============================================================ -expect(S.array().items(S.string())).type.toHaveProperty('items') -expect(S.array().additionalItems(true)).type.toHaveProperty('additionalItems') -expect(S.array().contains(S.string())).type.toHaveProperty('contains') -expect(S.array().uniqueItems(true)).type.toHaveProperty('uniqueItems') -expect(S.array().minItems(1)).type.toHaveProperty('minItems') -expect(S.array().maxItems(10)).type.toHaveProperty('maxItems') - -// ============================================================ -// ArraySchema return type -// ============================================================ -expect(S.array().items(S.string())).type.toEqual() -expect(S.array().uniqueItems(true)).type.toEqual() - -// ============================================================ -// ObjectSchema method chains -// ============================================================ -expect(S.object().prop('foo', S.string())).type.toHaveProperty('prop') -expect(S.object().definition('bar', S.number())).type.toHaveProperty('definition') -expect(S.object().additionalProperties(false)).type.toHaveProperty('additionalProperties') -expect(S.object().extend(S.object())).type.toHaveProperty('extend') -expect(S.object().only(['foo'])).type.toHaveProperty('only') -expect(S.object().without(['foo'])).type.toHaveProperty('without') -expect(S.object().dependentRequired({ foo: ['bar'] })).type.toHaveProperty('dependentRequired') -expect(S.object().dependentSchemas({ foo: S.object().prop('bar') })).type.toHaveProperty('dependentSchemas') -expect(S.object().maxProperties(10)).type.toHaveProperty('maxProperties') -expect(S.object().minProperties(1)).type.toHaveProperty('minProperties') - -// ============================================================ -// FORMATS assertions -// ============================================================ -expect(S.FORMATS.EMAIL).type.toEqual<'email'>() -expect(S.FORMATS.UUID).type.toEqual<'uuid'>() -expect(S.FORMATS.DATE_TIME).type.toEqual<'date-time'>() -expect(S.FORMATS.ISO_TIME).type.toEqual<'iso-time'>() -expect(S.FORMATS.ISO_DATE_TIME).type.toEqual<'iso-date-time'>() -expect(S.FORMATS.TIME).type.toEqual<'time'>() -expect(S.FORMATS.DATE).type.toEqual<'date'>() -expect(S.FORMATS.URL).type.toEqual<'url'>() -expect(S.FORMATS.IPV4).type.toEqual<'ipv4'>() -expect(S.FORMATS.IPV6).type.toEqual<'ipv6'>() - -// ============================================================ -// FluentSchemaError instanceof check -// ============================================================ -try { - S.object().prop('foo', 'boom!' as any) -} catch (e) { - if (e instanceof FluentSchemaError) { - expect(e).type.toEqual() - } -} - -// ============================================================ -// MixedSchema assertions -// ============================================================ -expect(S.mixed(['string'])).type.toHaveProperty('minLength') -expect(S.mixed(['string', 'integer'])).type.toHaveProperty('minLength') -expect(S.mixed(['string', 'number'])).type.toHaveProperty('minimum') +const schema = S.object() + .id('http://foo.com/user') + .title('A User') + .description('A User desc') + .definition( + 'address', + S.object() + .id('#address') + .prop('line1', S.anyOf([S.string(), S.null()])) // JSON Schema nullable + .prop('line2', S.string().raw({ nullable: true })) // Open API / Swagger nullable + .prop('country') + .allOf([S.string()]) + .prop('city') + .prop('zipcode') + ) + .prop('username', S.string().pattern(/[a-z]*/g)) + .prop('email', S.string().format('email')) + .prop('email2', S.string().format(S.FORMATS.EMAIL)) + .prop( + 'avatar', + S.string().contentEncoding('base64').contentMediaType('image/png') + ) + .required() + .prop( + 'password', + S.string().default('123456').minLength(6).maxLength(12).pattern('.*') + ) + .required() + .prop('addresses', S.array().items([S.ref('#address')])) + .required() + .prop( + 'role', + S.object() + .id('http://foo.com/role') + .prop('name') + .enum(['ADMIN', 'USER']) + .prop('permissions') + ) + .required() + .prop('age', S.mixed(['string', 'integer'])) + .ifThen(S.object().prop('age', S.string()), S.required(['age'])) + .readOnly() + .writeOnly(true) + .valueOf() + +const userBaseSchema = S.object() + .additionalProperties(false) + .prop('username', S.string()) + .prop('password', S.string()) -// ============================================================ -// Complex schema building (preserves fluency) -// ============================================================ const userSchema = S.object() .prop('id', S.string().format('uuid')) - .prop('name', S.string()) - .prop('email', S.string().format('email')) - .prop('age', S.number()) - -expect(userSchema).type.toHaveProperty('prop') -expect(userSchema).type.toHaveProperty('isFluentSchema') + .prop('createdAt', S.string().format('time')) + .prop('updatedAt', S.string().format('time')) + .extend(userBaseSchema) -// ============================================================ -// Extend returns ExtendedSchema type -// ============================================================ -const baseSchema = S.object().prop('createdAt', S.string()) -const extendedSchema = S.object().prop('id', S.string()).extend(baseSchema) +const largeUserSchema = S.object() + .prop('id', S.string().format('uuid')) + .prop('username', S.string()) + .prop('password', S.string()) + .prop('createdAt', S.string().format('time')) + .prop('updatedAt', S.string().format('time')) -expect(extendedSchema).type.toHaveProperty('extend') +const userSubsetSchema = largeUserSchema.only(['username', 'password']) -// ============================================================ -// Chained methods preserve correct types -// ============================================================ -expect(S.string().minLength(5).maxLength(10).pattern(/^\w+$/).format('email')) - .type.toEqual() +const personSchema = S.object() + .prop('name', S.string()) + .prop('age', S.number()) + .prop('id', S.string().format('uuid')) + .prop('createdAt', S.string().format('time')) + .prop('updatedAt', S.string().format('time')) -expect(S.number().minimum(0).maximum(100).multipleOf(5)) - .type.toEqual() +const bodySchema = personSchema.without(['createdAt', 'updatedAt']) -expect(S.array().items(S.string()).minItems(1).maxItems(10)) - .type.toEqual() +const personSchemaAllowsUnix = S.object() + .prop('name', S.string()) + .prop('age', S.number()) + .prop('id', S.string().format('uuid')) + .prop('createdAt', S.mixed(['string', 'integer']).format('time')) + .prop('updatedAt', S.mixed(['string', 'integer']).minimum(0)) -// ============================================================ -// Type parameter propagation (generics) -// ============================================================ -type User = { - id: string - name: string - email: string +try { + S.object().prop('foo', 'boom!' as any) +} catch (e) { + if (e instanceof FluentSchemaError) { + expect(e).type.toEqual() + } } -const typedSchema = S.object() - .prop('id', S.string().format('uuid')) - .prop('name', S.string()) - .prop('email', S.string().format('email')) - -expect(typedSchema).type.toHaveProperty('prop') +const arrayExtendedSchema = S.array().items(userSchema).valueOf() + +const extendExtendedSchema = S.object().extend(userSchema) + +const rawNullableSchema = S.object() + .raw({ nullable: true }) + .required(['foo', 'hello']) + .prop('foo', S.string()) + .prop('hello', S.string()) + +const dependentRequired = S.object() + .dependentRequired({ + foo: ['bar'], + }) + .prop('foo') + .prop('bar') + .valueOf() + +const dependentSchemas = S.object() + .dependentSchemas({ + foo: S.object().prop('bar'), + }) + .prop('bar', S.object().prop('bar')) + .valueOf() + +const deprecatedSchema = S.object() + .deprecated() + .prop('foo', S.string().deprecated()) + .valueOf() + +type Foo = { + foo: string + bar: string +} -// Using only/without creates subset types -const subsetSchema = typedSchema.only(['id', 'name']) +const dependentRequiredWithType = S.object() + .dependentRequired({ + foo: ['bar'], + }) + .prop('foo') + .prop('bar') + .valueOf() + +const dependentSchemasWithType = S.object() + .dependentSchemas({ + foo: S.object().prop('bar'), + }) + .prop('bar', S.object().prop('bar')) + .valueOf() + +const deprecatedSchemaWithType = S.object() + .deprecated() + .prop('foo', S.string().deprecated()) + .valueOf() + +type ReallyLongType = { + foo: string + bar: string + baz: string + xpto: string + abcd: number + kct: { + a: string + b: number + d: null + } +} -expect(subsetSchema).type.toHaveProperty('only') +const deepTestOnTypes = S.object() + .prop('bar', S.object().prop('bar')) + // you can provide any string, to avoid breaking changes + .prop('aaaa', S.anyOf([S.string()])) + .definition('abcd', S.number()) + .valueOf() + +const tsIsoSchema = S.object() + .prop('createdAt', S.string().format('iso-time')) + .prop('updatedAt', S.string().format('iso-date-time')) + .valueOf() From 2f31de3bb57460b0d96817528d5b640377ff35c3 Mon Sep 17 00:00:00 2001 From: Puppo Date: Wed, 6 May 2026 17:56:43 +0000 Subject: [PATCH 4/7] test: add tstyche type assertions to existing examples - Migrate from tsd to tstyche - Add 42 type assertions to existing code examples - Verify methods exist on schema objects using toHaveProperty - Test FluentSchemaError instanceof type --- types/FluentJSONSchema.tst.ts | 93 +++++++++++++++++++++++++++++++---- 1 file changed, 83 insertions(+), 10 deletions(-) diff --git a/types/FluentJSONSchema.tst.ts b/types/FluentJSONSchema.tst.ts index 52f0504..f2c791b 100644 --- a/types/FluentJSONSchema.tst.ts +++ b/types/FluentJSONSchema.tst.ts @@ -1,3 +1,5 @@ +// This file will be passed to the TypeScript CLI to verify our typings compile + import { expect } from 'tstyche' import S, { FluentSchemaError } from '..' @@ -49,19 +51,50 @@ const schema = S.object() .ifThen(S.object().prop('age', S.string()), S.required(['age'])) .readOnly() .writeOnly(true) - .valueOf() + +// Assertions for schema methods BEFORE valueOf +expect(schema).type.toHaveProperty('id') +expect(schema).type.toHaveProperty('title') +expect(schema).type.toHaveProperty('description') +expect(schema).type.toHaveProperty('definition') +expect(schema).type.toHaveProperty('prop') +expect(schema).type.toHaveProperty('required') +expect(schema).type.toHaveProperty('isFluentSchema') +expect(schema).type.toHaveProperty('readOnly') +expect(schema).type.toHaveProperty('writeOnly') + +// String method chain assertions +expect(S.string().pattern(/[a-z]*/g)).type.toHaveProperty('pattern') +expect(S.string().format('email')).type.toHaveProperty('format') +expect(S.string().format(S.FORMATS.EMAIL)).type.toHaveProperty('format') +expect(S.string().contentEncoding('base64')).type.toHaveProperty('contentEncoding') +expect(S.string().contentMediaType('image/png')).type.toHaveProperty('contentMediaType') +expect(S.string().minLength(6)).type.toHaveProperty('minLength') +expect(S.string().maxLength(12)).type.toHaveProperty('maxLength') +expect(S.string().default('123456')).type.toHaveProperty('default') + +console.log('example:\n', JSON.stringify(schema.valueOf())) +console.log('isFluentSchema:', S.object().isFluentSchema) const userBaseSchema = S.object() .additionalProperties(false) .prop('username', S.string()) .prop('password', S.string()) +// ObjectSchema methods assertions +expect(userBaseSchema).type.toHaveProperty('additionalProperties') +expect(userBaseSchema).type.toHaveProperty('prop') + const userSchema = S.object() .prop('id', S.string().format('uuid')) .prop('createdAt', S.string().format('time')) .prop('updatedAt', S.string().format('time')) .extend(userBaseSchema) +expect(userSchema).type.toHaveProperty('extend') + +console.log('user:\n', JSON.stringify(userSchema.valueOf())) + const largeUserSchema = S.object() .prop('id', S.string().format('uuid')) .prop('username', S.string()) @@ -71,6 +104,9 @@ const largeUserSchema = S.object() const userSubsetSchema = largeUserSchema.only(['username', 'password']) +console.log('user subset:', JSON.stringify(userSubsetSchema.valueOf())) +expect(userSubsetSchema).type.toHaveProperty('only') + const personSchema = S.object() .prop('name', S.string()) .prop('age', S.number()) @@ -80,6 +116,9 @@ const personSchema = S.object() const bodySchema = personSchema.without(['createdAt', 'updatedAt']) +console.log('person subset:', JSON.stringify(bodySchema.valueOf())) +expect(bodySchema).type.toHaveProperty('without') + const personSchemaAllowsUnix = S.object() .prop('name', S.string()) .prop('age', S.number()) @@ -87,43 +126,63 @@ const personSchemaAllowsUnix = S.object() .prop('createdAt', S.mixed(['string', 'integer']).format('time')) .prop('updatedAt', S.mixed(['string', 'integer']).minimum(0)) +console.log('person schema allows unix:', JSON.stringify(personSchemaAllowsUnix.valueOf())) +expect(personSchemaAllowsUnix).type.toHaveProperty('prop') + try { S.object().prop('foo', 'boom!' as any) } catch (e) { if (e instanceof FluentSchemaError) { + console.log(e.message) expect(e).type.toEqual() } } -const arrayExtendedSchema = S.array().items(userSchema).valueOf() +const arrayExtendedSchema = S.array().items(userSchema) + +console.log('array of user\n', JSON.stringify(arrayExtendedSchema.valueOf())) +expect(arrayExtendedSchema).type.toHaveProperty('items') const extendExtendedSchema = S.object().extend(userSchema) +console.log('extend of user\n', JSON.stringify(extendExtendedSchema.valueOf())) +expect(extendExtendedSchema).type.toHaveProperty('extend') + const rawNullableSchema = S.object() .raw({ nullable: true }) .required(['foo', 'hello']) .prop('foo', S.string()) .prop('hello', S.string()) +console.log('raw schema with nullable props\n', JSON.stringify(rawNullableSchema.valueOf())) +expect(rawNullableSchema).type.toHaveProperty('raw') +expect(rawNullableSchema).type.toHaveProperty('required') + const dependentRequired = S.object() .dependentRequired({ foo: ['bar'], }) .prop('foo') .prop('bar') - .valueOf() + +console.log('dependentRequired:\n', JSON.stringify(dependentRequired.valueOf())) +expect(dependentRequired).type.toHaveProperty('dependentRequired') const dependentSchemas = S.object() .dependentSchemas({ foo: S.object().prop('bar'), }) .prop('bar', S.object().prop('bar')) - .valueOf() + +console.log('dependentRequired:\n', JSON.stringify(dependentSchemas.valueOf())) +expect(dependentSchemas).type.toHaveProperty('dependentSchemas') const deprecatedSchema = S.object() .deprecated() .prop('foo', S.string().deprecated()) - .valueOf() + +console.log('deprecatedSchema:\n', JSON.stringify(deprecatedSchema.valueOf())) +expect(deprecatedSchema).type.toHaveProperty('deprecated') type Foo = { foo: string @@ -136,19 +195,26 @@ const dependentRequiredWithType = S.object() }) .prop('foo') .prop('bar') - .valueOf() + +console.log('dependentRequired:\n', JSON.stringify(dependentRequiredWithType.valueOf())) +expect(dependentRequiredWithType).type.toHaveProperty('dependentRequired') +expect(dependentRequiredWithType).type.toHaveProperty('prop') const dependentSchemasWithType = S.object() .dependentSchemas({ foo: S.object().prop('bar'), }) .prop('bar', S.object().prop('bar')) - .valueOf() + +console.log('dependentSchemasWithType:\n', JSON.stringify(dependentSchemasWithType.valueOf())) +expect(dependentSchemasWithType).type.toHaveProperty('dependentSchemas') const deprecatedSchemaWithType = S.object() .deprecated() .prop('foo', S.string().deprecated()) - .valueOf() + +console.log('deprecatedSchemaWithType:\n', JSON.stringify(deprecatedSchemaWithType.valueOf())) +expect(deprecatedSchemaWithType).type.toHaveProperty('deprecated') type ReallyLongType = { foo: string @@ -168,9 +234,16 @@ const deepTestOnTypes = S.object() // you can provide any string, to avoid breaking changes .prop('aaaa', S.anyOf([S.string()])) .definition('abcd', S.number()) - .valueOf() + +console.log('deepTestOnTypes:\n', JSON.stringify(deepTestOnTypes.valueOf())) +expect(deepTestOnTypes).type.toHaveProperty('prop') +expect(deepTestOnTypes).type.toHaveProperty('definition') const tsIsoSchema = S.object() .prop('createdAt', S.string().format('iso-time')) .prop('updatedAt', S.string().format('iso-date-time')) - .valueOf() + +console.log('ISO schema OK:', JSON.stringify(tsIsoSchema.valueOf())) +expect(tsIsoSchema).type.toHaveProperty('prop') +expect(S.string().format('iso-time')).type.toHaveProperty('format') +expect(S.string().format('iso-date-time')).type.toHaveProperty('format') From 5c3375d39719b07c8fd16fb7d2483f72a4162fd7 Mon Sep 17 00:00:00 2001 From: Puppo Date: Wed, 6 May 2026 19:43:56 +0000 Subject: [PATCH 5/7] chore: upgrade tstyche to v7.1.0 - Update tstyche from 1.0.0 to 7.1.0 - Update assertions to use toBe instead of toEqual --- package.json | 2 +- types/FluentJSONSchema.tst.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 07c8274..e06e052 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "jsdoc-to-markdown": "^9.0.0", "lodash.merge": "^4.6.2", "neostandard": "^0.13.0", - "tstyche": "^1.0.0" + "tstyche": "^7.1.0" }, "dependencies": { "@fastify/deepmerge": "^3.0.0" diff --git a/types/FluentJSONSchema.tst.ts b/types/FluentJSONSchema.tst.ts index f2c791b..623702e 100644 --- a/types/FluentJSONSchema.tst.ts +++ b/types/FluentJSONSchema.tst.ts @@ -5,8 +5,8 @@ import { expect } from 'tstyche' import S, { FluentSchemaError } from '..' // isFluentJSONSchema and isFluentSchema properties -expect(S.object().isFluentJSONSchema).type.toEqual() -expect(S.object().isFluentSchema).type.toEqual() +expect(S.object().isFluentJSONSchema).type.toBe() +expect(S.object().isFluentSchema).type.toBe() const schema = S.object() .id('http://foo.com/user') @@ -134,7 +134,7 @@ try { } catch (e) { if (e instanceof FluentSchemaError) { console.log(e.message) - expect(e).type.toEqual() + expect(e).type.toBe() } } From e18889959b3a8b85fb2bef40fa1fc5d8ced6cb74 Mon Sep 17 00:00:00 2001 From: Luca Del Puppo Date: Thu, 7 May 2026 13:23:16 +0200 Subject: [PATCH 6/7] test: replace console logs with type assertions for schema validation --- types/FluentJSONSchema.tst.ts | 36 +++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/types/FluentJSONSchema.tst.ts b/types/FluentJSONSchema.tst.ts index 623702e..ec2720e 100644 --- a/types/FluentJSONSchema.tst.ts +++ b/types/FluentJSONSchema.tst.ts @@ -73,8 +73,8 @@ expect(S.string().minLength(6)).type.toHaveProperty('minLength') expect(S.string().maxLength(12)).type.toHaveProperty('maxLength') expect(S.string().default('123456')).type.toHaveProperty('default') -console.log('example:\n', JSON.stringify(schema.valueOf())) -console.log('isFluentSchema:', S.object().isFluentSchema) +expect(schema.valueOf()).type.toBe() +expect(S.object().isFluentSchema).type.toBe() const userBaseSchema = S.object() .additionalProperties(false) @@ -93,7 +93,7 @@ const userSchema = S.object() expect(userSchema).type.toHaveProperty('extend') -console.log('user:\n', JSON.stringify(userSchema.valueOf())) +expect(userSchema.valueOf()).type.toBe() const largeUserSchema = S.object() .prop('id', S.string().format('uuid')) @@ -104,7 +104,7 @@ const largeUserSchema = S.object() const userSubsetSchema = largeUserSchema.only(['username', 'password']) -console.log('user subset:', JSON.stringify(userSubsetSchema.valueOf())) +expect(userSubsetSchema.valueOf()).type.toBe() expect(userSubsetSchema).type.toHaveProperty('only') const personSchema = S.object() @@ -116,7 +116,7 @@ const personSchema = S.object() const bodySchema = personSchema.without(['createdAt', 'updatedAt']) -console.log('person subset:', JSON.stringify(bodySchema.valueOf())) +expect(bodySchema.valueOf()).type.toBe() expect(bodySchema).type.toHaveProperty('without') const personSchemaAllowsUnix = S.object() @@ -126,26 +126,26 @@ const personSchemaAllowsUnix = S.object() .prop('createdAt', S.mixed(['string', 'integer']).format('time')) .prop('updatedAt', S.mixed(['string', 'integer']).minimum(0)) -console.log('person schema allows unix:', JSON.stringify(personSchemaAllowsUnix.valueOf())) +expect(personSchemaAllowsUnix.valueOf()).type.toBe() expect(personSchemaAllowsUnix).type.toHaveProperty('prop') try { S.object().prop('foo', 'boom!' as any) } catch (e) { if (e instanceof FluentSchemaError) { - console.log(e.message) + expect(e.message).type.toBe() expect(e).type.toBe() } } const arrayExtendedSchema = S.array().items(userSchema) -console.log('array of user\n', JSON.stringify(arrayExtendedSchema.valueOf())) +expect(arrayExtendedSchema.valueOf()).type.toBe() expect(arrayExtendedSchema).type.toHaveProperty('items') const extendExtendedSchema = S.object().extend(userSchema) -console.log('extend of user\n', JSON.stringify(extendExtendedSchema.valueOf())) +expect(extendExtendedSchema.valueOf()).type.toBe() expect(extendExtendedSchema).type.toHaveProperty('extend') const rawNullableSchema = S.object() @@ -154,7 +154,7 @@ const rawNullableSchema = S.object() .prop('foo', S.string()) .prop('hello', S.string()) -console.log('raw schema with nullable props\n', JSON.stringify(rawNullableSchema.valueOf())) +expect(rawNullableSchema.valueOf()).type.toBe() expect(rawNullableSchema).type.toHaveProperty('raw') expect(rawNullableSchema).type.toHaveProperty('required') @@ -165,7 +165,7 @@ const dependentRequired = S.object() .prop('foo') .prop('bar') -console.log('dependentRequired:\n', JSON.stringify(dependentRequired.valueOf())) +expect(dependentRequired.valueOf()).type.toBe() expect(dependentRequired).type.toHaveProperty('dependentRequired') const dependentSchemas = S.object() @@ -174,14 +174,14 @@ const dependentSchemas = S.object() }) .prop('bar', S.object().prop('bar')) -console.log('dependentRequired:\n', JSON.stringify(dependentSchemas.valueOf())) +expect(dependentSchemas.valueOf()).type.toBe() expect(dependentSchemas).type.toHaveProperty('dependentSchemas') const deprecatedSchema = S.object() .deprecated() .prop('foo', S.string().deprecated()) -console.log('deprecatedSchema:\n', JSON.stringify(deprecatedSchema.valueOf())) +expect(deprecatedSchema.valueOf()).type.toBe() expect(deprecatedSchema).type.toHaveProperty('deprecated') type Foo = { @@ -196,7 +196,7 @@ const dependentRequiredWithType = S.object() .prop('foo') .prop('bar') -console.log('dependentRequired:\n', JSON.stringify(dependentRequiredWithType.valueOf())) +expect(dependentRequiredWithType.valueOf()).type.toBe() expect(dependentRequiredWithType).type.toHaveProperty('dependentRequired') expect(dependentRequiredWithType).type.toHaveProperty('prop') @@ -206,14 +206,14 @@ const dependentSchemasWithType = S.object() }) .prop('bar', S.object().prop('bar')) -console.log('dependentSchemasWithType:\n', JSON.stringify(dependentSchemasWithType.valueOf())) +expect(dependentSchemasWithType.valueOf()).type.toBe() expect(dependentSchemasWithType).type.toHaveProperty('dependentSchemas') const deprecatedSchemaWithType = S.object() .deprecated() .prop('foo', S.string().deprecated()) -console.log('deprecatedSchemaWithType:\n', JSON.stringify(deprecatedSchemaWithType.valueOf())) +expect(deprecatedSchemaWithType.valueOf()).type.toBe() expect(deprecatedSchemaWithType).type.toHaveProperty('deprecated') type ReallyLongType = { @@ -235,7 +235,7 @@ const deepTestOnTypes = S.object() .prop('aaaa', S.anyOf([S.string()])) .definition('abcd', S.number()) -console.log('deepTestOnTypes:\n', JSON.stringify(deepTestOnTypes.valueOf())) +expect(deepTestOnTypes.valueOf()).type.toBe() expect(deepTestOnTypes).type.toHaveProperty('prop') expect(deepTestOnTypes).type.toHaveProperty('definition') @@ -243,7 +243,7 @@ const tsIsoSchema = S.object() .prop('createdAt', S.string().format('iso-time')) .prop('updatedAt', S.string().format('iso-date-time')) -console.log('ISO schema OK:', JSON.stringify(tsIsoSchema.valueOf())) +expect(tsIsoSchema.valueOf()).type.toBe() expect(tsIsoSchema).type.toHaveProperty('prop') expect(S.string().format('iso-time')).type.toHaveProperty('format') expect(S.string().format('iso-date-time')).type.toHaveProperty('format') From 7a5be72d4b337756da8129d19fab2506129f1e00 Mon Sep 17 00:00:00 2001 From: Luca Del Puppo Date: Thu, 7 May 2026 13:36:13 +0200 Subject: [PATCH 7/7] chore: remove tsconfig.json and clean up type test file --- tsconfig.json | 10 ---------- types/FluentJSONSchema.tst.ts | 2 -- 2 files changed, 12 deletions(-) delete mode 100644 tsconfig.json diff --git a/tsconfig.json b/tsconfig.json deleted file mode 100644 index a38676d..0000000 --- a/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "compilerOptions": { - "module": "node16", - "moduleResolution": "node16", - "noEmit": true, - "strict": true, - "types": ["tstyche"] - }, - "include": ["types/**/*.ts"] -} diff --git a/types/FluentJSONSchema.tst.ts b/types/FluentJSONSchema.tst.ts index ec2720e..4994d73 100644 --- a/types/FluentJSONSchema.tst.ts +++ b/types/FluentJSONSchema.tst.ts @@ -1,5 +1,3 @@ -// This file will be passed to the TypeScript CLI to verify our typings compile - import { expect } from 'tstyche' import S, { FluentSchemaError } from '..'