Skip to content

Commit 2e98364

Browse files
mjwwitEthan-Arrowood
authored andcommitted
Add TypeScript type declaration file (fixes #148) (#156)
* Add TypeScript type declaration file (fixes #148) * Improve types and add tests for types * Add types for options and nullable
1 parent 8cc44d1 commit 2e98364

File tree

4 files changed

+330
-1
lines changed

4 files changed

+330
-1
lines changed

index.d.ts

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
import { Options as AjvOptions } from "ajv"
2+
declare namespace build {
3+
interface BaseSchema {
4+
/**
5+
* Schema title
6+
*/
7+
title?: string;
8+
/**
9+
* Schema description
10+
*/
11+
description?: string;
12+
/**
13+
* A comment to be added to the schema
14+
*/
15+
$comment?: string;
16+
/**
17+
* Default value to be assigned when no value is given in the document
18+
*/
19+
default?: any;
20+
/**
21+
* A list of example values that match this schema
22+
*/
23+
examples?: any[];
24+
/**
25+
* Additional schema definition to reference from within the schema
26+
*/
27+
definitions?: Record<string, Schema>
28+
/**
29+
* A set of schemas of which at least one must match
30+
*/
31+
anyOf?: Partial<Schema>[];
32+
/**
33+
* A set of schemas which must all match
34+
*/
35+
allOf?: Partial<Schema>[];
36+
/**
37+
* A conditional schema to check, controls schemas defined in `then` and `else`
38+
*/
39+
if?: Partial<Schema>;
40+
/**
41+
* A schema to apply if the conditional schema from `if` passes
42+
*/
43+
then?: Partial<Schema>;
44+
/**
45+
* A schema to apply if the conditional schema from `if` fails
46+
*/
47+
else?: Partial<Schema>;
48+
/**
49+
* Open API 3.0 spec states that any value that can be null must be declared `nullable`
50+
* @default false
51+
*/
52+
nullable?: boolean;
53+
}
54+
55+
export interface RefSchema {
56+
/**
57+
* A json-pointer to a schema to use as a reference
58+
*/
59+
$ref: string;
60+
}
61+
62+
export interface StringSchema extends BaseSchema {
63+
type: "string";
64+
}
65+
66+
export interface IntegerSchema extends BaseSchema {
67+
type: "integer";
68+
}
69+
70+
export interface NumberSchema extends BaseSchema {
71+
type: "number";
72+
}
73+
74+
export interface NullSchema extends BaseSchema {
75+
type: "null";
76+
}
77+
78+
export interface BooleanSchema extends BaseSchema {
79+
type: "boolean";
80+
}
81+
82+
export interface ArraySchema extends BaseSchema {
83+
type: "array";
84+
/**
85+
* The schema for the items in the array
86+
*/
87+
items: Schema | {}
88+
}
89+
90+
export interface TupleSchema extends BaseSchema {
91+
type: "array";
92+
/**
93+
* The schemas for the items in the tuple
94+
*/
95+
items: Schema[];
96+
}
97+
98+
type ObjectProperties = Record<string, Partial<Schema>> & {
99+
anyOf?: ObjectProperties[];
100+
allOf?: ObjectProperties[];
101+
if?: ObjectProperties;
102+
then?: ObjectProperties;
103+
else?: ObjectProperties;
104+
}
105+
106+
export interface ObjectSchema extends BaseSchema {
107+
type: "object";
108+
/**
109+
* Describe the properties of the object
110+
*/
111+
properties?: ObjectProperties;
112+
/**
113+
* The required properties of the object
114+
*/
115+
required?: string[];
116+
/**
117+
* Describe properties that have keys following a given pattern
118+
*/
119+
patternProperties?: ObjectProperties;
120+
/**
121+
* Specifies whether additional properties on the object are allowed, and optionally what schema they should
122+
* adhere to
123+
* @default false
124+
*/
125+
additionalProperties?: Schema | boolean;
126+
}
127+
128+
export type Schema =
129+
| RefSchema
130+
| StringSchema
131+
| IntegerSchema
132+
| NumberSchema
133+
| NullSchema
134+
| BooleanSchema
135+
| ArraySchema
136+
| TupleSchema
137+
| ObjectSchema;
138+
139+
export interface Options {
140+
/**
141+
* Optionally add an external definition to reference from your schema
142+
*/
143+
schema?: Record<string, Schema>
144+
/**
145+
* Uglify the generated serialization function to get a performance increase on Node.js versions lower than 8.3.0
146+
*/
147+
uglify?: boolean
148+
/**
149+
* Configure Ajv, which is used to evaluate conditional schemas and combined (anyOf) schemas
150+
*/
151+
ajv?: AjvOptions
152+
}
153+
}
154+
155+
/**
156+
* Build a stringify function using a schema of the documents that should be stringified
157+
* @param schema The schema used to stringify values
158+
* @param options The options to use (optional)
159+
*/
160+
declare function build(schema: build.StringSchema, options?: build.Options): (doc: string) => string;
161+
declare function build(schema: build.IntegerSchema | build.NumberSchema, options?: build.Options): (doc: number) => string;
162+
declare function build(schema: build.NullSchema, options?: build.Options): (doc: null) => "null";
163+
declare function build(schema: build.BooleanSchema, options?: build.Options): (doc: boolean) => string;
164+
declare function build(schema: build.ArraySchema | build.TupleSchema, options?: build.Options): (doc: any[]) => string;
165+
declare function build(schema: build.ObjectSchema, options?: build.Options): (doc: object) => string;
166+
declare function build(schema: build.Schema, options?: build.Options): (doc: object | any[] | string | number | boolean | null) => string;
167+
168+
export = build;

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
"version": "1.13.1",
44
"description": "Stringify your JSON at max speed",
55
"main": "index.js",
6+
"types": "index.d.ts",
67
"scripts": {
78
"benchmark": "node bench.js",
89
"test:lint": "standard",
10+
"test:typescript": "tsc --project ./test/types/tsconfig.json",
911
"test:unit": "tap -J test/*.test.js test/**/*.test.js",
10-
"test": "npm run test:lint && npm run test:unit",
12+
"test": "npm run test:lint && npm run test:unit && npm run test:typescript",
1113
"test:report": "npm run test:unit | tee out.tap",
1214
"test:reporter": "tap-mocha-reporter xunit < out.tap > test/junit-testresults.xml"
1315
},
@@ -37,6 +39,7 @@
3739
"standard": "^12.0.1",
3840
"tap": "^12.5.1",
3941
"tap-mocha-reporter": "^3.0.9",
42+
"typescript": "^3.0.0",
4043
"uglify-es": "^3.3.9"
4144
},
4245
"dependencies": {

test/types/test.ts

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
import build, { Schema } from '../..'
2+
3+
// Number schemas
4+
const schema1: Schema = {
5+
type: 'number'
6+
}
7+
const schema2: Schema = {
8+
type: 'integer'
9+
}
10+
11+
build(schema1)(25)
12+
build(schema2)(-5)
13+
14+
// String schema
15+
const schema3: Schema = {
16+
type: 'string'
17+
}
18+
19+
build(schema3)('foobar')
20+
21+
// Boolean schema
22+
const schema4: Schema = {
23+
type: 'boolean'
24+
}
25+
26+
build(schema4)(true)
27+
28+
// Null schema
29+
const schema5: Schema = {
30+
type: 'null'
31+
}
32+
33+
build(schema5)(null)
34+
35+
// Array schemas
36+
const schema6: Schema = {
37+
type: 'array',
38+
items: { type: 'number' }
39+
}
40+
const schema7: Schema = {
41+
type: 'array',
42+
items: [{ type: 'string'}, {type: 'integer'}]
43+
}
44+
45+
build(schema6)([25])
46+
build(schema7)(['hello', 42])
47+
48+
// Object schemas
49+
const schema8: Schema = {
50+
type: 'object'
51+
}
52+
const schema9: Schema = {
53+
type: 'object',
54+
properties: {
55+
foo: { type: 'string' },
56+
bar: { type: 'integer' }
57+
},
58+
required: ['foo'],
59+
patternProperties: {
60+
'baz*': { type: 'null' }
61+
},
62+
additionalProperties: {
63+
type: 'boolean'
64+
}
65+
}
66+
67+
build(schema8)({})
68+
build(schema9)({ foo: 'bar' })
69+
70+
// Reference schemas
71+
const schema10: Schema = {
72+
title: 'Example Schema',
73+
definitions: {
74+
num: {
75+
type: 'object',
76+
properties: {
77+
int: {
78+
type: 'integer'
79+
}
80+
}
81+
},
82+
str: {
83+
type: 'string'
84+
},
85+
def: {
86+
type: 'null'
87+
}
88+
},
89+
type: 'object',
90+
properties: {
91+
nickname: {
92+
$ref: '#/definitions/str'
93+
}
94+
},
95+
patternProperties: {
96+
'num': {
97+
$ref: '#/definitions/num'
98+
}
99+
},
100+
additionalProperties: {
101+
$ref: '#/definitions/def'
102+
}
103+
}
104+
105+
build(schema10)({ nickname: '', num: { int: 5 }, other: null })
106+
107+
// Conditional/Combined schemas
108+
const schema11: Schema = {
109+
title: 'Conditional/Combined Schema',
110+
type: 'object',
111+
properties: {
112+
something: {
113+
anyOf: [
114+
{ type: 'string' },
115+
{ type: 'boolean' }
116+
]
117+
}
118+
},
119+
if: {
120+
properties: {
121+
something: { type: 'string' }
122+
}
123+
},
124+
then: {
125+
properties: {
126+
somethingElse: { type: 'number' }
127+
}
128+
},
129+
else: {
130+
properties: {
131+
somethingElse: { type: 'null' }
132+
}
133+
}
134+
}
135+
136+
build(schema11)({ something: 'a string', somethingElse: 42 })
137+
138+
// With options
139+
const schema12: Schema = {
140+
title: 'Some Schema',
141+
type: 'object',
142+
properties: {
143+
str: { $ref: '#/definitions/string' }
144+
}
145+
}
146+
147+
build(schema12, { schema: { string: { type: 'string' } }, uglify: true, ajv: { jsonPointers: true } })

test/types/tsconfig.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"compilerOptions": {
3+
"esModuleInterop": true,
4+
"noEmit": true,
5+
"rootDir": "../..",
6+
"strict": true
7+
},
8+
"include": [
9+
"./test.ts"
10+
]
11+
}

0 commit comments

Comments
 (0)