Skip to content

Fix coercion types #683

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,9 @@ interface StandaloneOption extends build.Options {
mode: 'standalone'
}

type StringCoercible = string | Date | RegExp;
type IntegerCoercible = number | BigInt;

/**
* Build a stringify function using a schema of the documents that should be stringified
* @param schema The schema used to stringify values
Expand All @@ -217,8 +220,8 @@ declare function build(schema: build.AnySchema, options: DebugOption): { code: s
declare function build(schema: build.AnySchema, options: DeprecateDebugOption): { code: string, ajv: Ajv };
declare function build(schema: build.AnySchema, options: StandaloneOption): string;
declare function build(schema: build.AnySchema, options?: build.Options): <TDoc = any>(doc: TDoc) => any;
declare function build(schema: build.StringSchema, options?: build.Options): <TDoc extends string = string>(doc: TDoc) => string;
declare function build(schema: build.IntegerSchema | build.NumberSchema, options?: build.Options): <TDoc extends number = number>(doc: TDoc) => string;
declare function build(schema: build.StringSchema, options?: build.Options): <TDoc extends StringCoercible = StringCoercible>(doc: TDoc) => string;
declare function build(schema: build.IntegerSchema | build.NumberSchema, options?: build.Options): <TDoc extends IntegerCoercible = IntegerCoercible>(doc: TDoc) => string;
declare function build(schema: build.NullSchema, options?: build.Options): <TDoc extends null = null>(doc: TDoc) => "null";
declare function build(schema: build.BooleanSchema, options?: build.Options): <TDoc extends boolean = boolean>(doc: TDoc) => string;
declare function build(schema: build.ArraySchema | build.TupleSchema, options?: build.Options): <TDoc extends any[]= any[]>(doc: TDoc) => string;
Expand Down
136 changes: 79 additions & 57 deletions types/index.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,61 +3,62 @@ import build, { restore, Schema, validLargeArrayMechanisms } from '..'
import { expectError, expectType } from 'tsd'

// Number schemas
const schema1: Schema = {
build({
type: 'number'
}
const schema2: Schema = {
})(25)
build({
type: 'integer'
}

build(schema1)(25)
build(schema2)(-5)
})(-5)
build({
type: 'integer'
})(5n)

build(schema2, { rounding: 'ceil' })
build(schema2, { rounding: 'floor' })
build(schema2, { rounding: 'round' })
build(schema2, { rounding: 'trunc' })
expectError(build(schema2, { rounding: 'invalid' }))
build({
type: 'number'
}, { rounding: 'ceil' })
build({
type: 'number'
}, { rounding: 'floor' })
build({
type: 'number'
}, { rounding: 'round' })
build({
type: 'number'
}, { rounding: 'trunc' })
expectError(build({
type: 'number'
}, { rounding: 'invalid' }))

// String schema
const schema3: Schema = {
type: 'string'
}

build(schema3)('foobar')
build({
type: 'string'
})('foobar')

// Boolean schema
const schema4: Schema = {
build({
type: 'boolean'
}

build(schema4)(true)
})(true)

// Null schema
const schema5: Schema = {
build({
type: 'null'
}

build(schema5)(null)
})(null)

// Array schemas
const schema6: Schema = {
build({
type: 'array',
items: { type: 'number' }
}
const schema7: Schema = {
})([25])
build({
type: 'array',
items: [{ type: 'string'}, {type: 'integer'}]
}

build(schema6)([25])
build(schema7)(['hello', 42])
})(['hello', 42])

// Object schemas
const schema8: Schema = {
build({
type: 'object'
}
const schema9: Schema = {
})({})
build({
type: 'object',
properties: {
foo: { type: 'string' },
Expand All @@ -70,14 +71,24 @@ const schema9: Schema = {
additionalProperties: {
type: 'boolean'
}
}

build(schema8)({})
build(schema9)({ foo: 'bar' })
build(schema9, { rounding: 'floor' })({ foo: 'bar' })
})({ foo: 'bar' })
build({
type: 'object',
properties: {
foo: { type: 'string' },
bar: { type: 'integer' }
},
required: ['foo'],
patternProperties: {
'baz*': { type: 'null' }
},
additionalProperties: {
type: 'boolean'
}
}, { rounding: 'floor' })({ foo: 'bar' })

// Reference schemas
const schema10: Schema = {
build({
title: 'Example Schema',
definitions: {
num: {
Expand Down Expand Up @@ -109,12 +120,10 @@ const schema10: Schema = {
additionalProperties: {
$ref: '#/definitions/def'
}
}

build(schema10)({ nickname: '', num: { int: 5 }, other: null })
})({ nickname: '', num: { int: 5 }, other: null })

// Conditional/Combined schemas
const schema11: Schema = {
build({
title: 'Conditional/Combined Schema',
type: 'object',
properties: {
Expand All @@ -140,24 +149,37 @@ const schema11: Schema = {
somethingElse: { type: 'null' }
}
}
}

build(schema11)({ something: 'a string', somethingElse: 42 })
})({ something: 'a string', somethingElse: 42 })

// String schema with format
const schema12: Schema = {

build({
type: 'string',
format: 'date-time'
}

build(schema12)(new Date())
})(new Date())

/*
This overload doesn't work yet -
TypeScript chooses the generic for the schema
before it chooses the overload for the options
parameter.
let str: string, ajv: Ajv
str = build(schema1, { debugMode: true }).code
ajv = build(schema1, { debugMode: true }).ajv
str = build(schema1, { mode: 'debug' }).code
ajv = build(schema1, { mode: 'debug' }).ajv
str = build(schema1, { mode: 'standalone' })
str = build({
type: 'number'
}, { debugMode: true }).code
ajv = build({
type: 'number'
}, { debugMode: true }).ajv
str = build({
type: 'number'
}, { mode: 'debug' }).code
ajv = build({
type: 'number'
}, { mode: 'debug' }).ajv
str = build({
type: 'number'
}, { mode: 'standalone' })
*/

const debugCompiled = build({
title: 'default string',
Expand Down