From 9d4ac46513c17bc37300baba834c7eb72de3f605 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20Unneb=C3=A4ck?= Date: Thu, 9 Aug 2018 19:43:20 +0100 Subject: [PATCH 1/6] Add toJSON to TypeScript typings --- index.d.ts | 18 ++++++++++++++---- test/typings.ts | 3 +++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/index.d.ts b/index.d.ts index 53507a4..005c146 100644 --- a/index.d.ts +++ b/index.d.ts @@ -67,11 +67,21 @@ declare namespace factory { } } -declare function createValidator (schema: ObjectSchema, options?: any): ((input: unknown, options?: any) => input is { [K in keyof T]: (K extends R ? ExtractSchemaType : ExtractSchemaType | undefined) }) & { errors: factory.ValidationError[] } -declare function createValidator (schema: T, options?: any): ((input: unknown, options?: any) => input is ExtractSchemaType) & { errors: factory.ValidationError[] } +declare interface Validator> { + (input: unknown, options?: any): input is Output + errors: factory.ValidationError[] + toJSON(): Schema +} + +declare function createValidator (schema: ObjectSchema, options?: any): Validator> +declare function createValidator (schema: T, options?: any): Validator + +declare interface Filter { + (input: Output, options?: any): Output +} -declare function createFilter (schema: ObjectSchema, options?: any): ((input: { [K in keyof T]: (K extends R ? ExtractSchemaType : ExtractSchemaType | undefined) }, options?: any) => { [K in keyof T]: (K extends R ? ExtractSchemaType : ExtractSchemaType | undefined) }) -declare function createFilter (schema: T, options?: any): ((input: ExtractSchemaType, options?: any) => ExtractSchemaType) +declare function createFilter (schema: ObjectSchema, options?: any): Filter> +declare function createFilter (schema: T, options?: any): Filter> declare type Factory = (typeof createValidator) & { filter: typeof createFilter } declare const factory: Factory diff --git a/test/typings.ts b/test/typings.ts index 425578d..2f96408 100644 --- a/test/typings.ts +++ b/test/typings.ts @@ -9,6 +9,7 @@ function assertType(value: T): void {} const input = null as unknown const nullValidator = createValidator({ type: 'null' }) +assertType<{ type: 'null' }>(nullValidator.toJSON()) if (nullValidator(input)) { assertType(input) @@ -22,12 +23,14 @@ assertType(nullValidator.errors[0].type) assertType(nullValidator.errors[0].value) const numberValidator = createValidator({ type: 'number' }) +assertType<{ type: 'number' }>(numberValidator.toJSON()) if (numberValidator(input)) { assertType(input) } const stringValidator = createValidator({ type: 'string' }) +assertType<{ type: 'string' }>(stringValidator.toJSON()) if (stringValidator(input)) { assertType(input) From 8ecbe380d053d6ba6d149a2b0038c00b58b736cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20Unneb=C3=A4ck?= Date: Thu, 9 Aug 2018 21:44:59 +0100 Subject: [PATCH 2/6] Refactor Factory definition --- index.d.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/index.d.ts b/index.d.ts index 005c146..246f50f 100644 --- a/index.d.ts +++ b/index.d.ts @@ -73,17 +73,18 @@ declare interface Validator> { toJSON(): Schema } -declare function createValidator (schema: ObjectSchema, options?: any): Validator> -declare function createValidator (schema: T, options?: any): Validator - declare interface Filter { (input: Output, options?: any): Output } -declare function createFilter (schema: ObjectSchema, options?: any): Filter> -declare function createFilter (schema: T, options?: any): Filter> +declare interface Factory { + (schema: ObjectSchema, options?: any): Validator> + (schema: T, options?: any): Validator + + createFilter (schema: ObjectSchema, options?: any): Filter> + createFilter (schema: T, options?: any): Filter> +} -declare type Factory = (typeof createValidator) & { filter: typeof createFilter } declare const factory: Factory export = factory From 3da57a4fb7c3c83da5f8ba9660ebf116cd0ebfe0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20Unneb=C3=A4ck?= Date: Thu, 9 Aug 2018 21:51:01 +0100 Subject: [PATCH 3/6] Refactor away LeafSchema and GenericSchema --- index.d.ts | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/index.d.ts b/index.d.ts index 246f50f..79e4554 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,3 +1,5 @@ +type AnySchema = NullSchema | BooleanSchema | NumberSchema | StringSchema | AnyEnumSchema | AnyArraySchema | AnyObjectSchema + interface NullSchema { type: 'null' } @@ -14,20 +16,19 @@ interface StringSchema { type: 'string' } -type LeafSchema = NullSchema | BooleanSchema | NumberSchema | StringSchema - +interface AnyEnumSchema extends EnumSchema {} interface EnumSchema { enum: T[] } -interface ArraySchema | ArraySchema | ObjectSchema> | ObjectSchema> { +interface AnyArraySchema extends ArraySchema {} +interface ArraySchema { type: 'array' items: T } -type ObjectProps = { [K in string]: LeafSchema | EnumSchema | ArraySchema | ArraySchema | ObjectSchema> | ObjectSchema> | ObjectSchema } - -interface ObjectSchema { +interface AnyObjectSchema extends ObjectSchema, string> {} +interface ObjectSchema, R extends keyof T> { additionalProperties?: boolean type: 'object' properties: T @@ -51,13 +52,6 @@ declare type ExtractSchemaType = ( : never ) -declare type GenericSchema = ( - { enum: any[] } | - { type: 'string' | 'number' | 'boolean' | 'null' } | - { type: 'array', items: GenericSchema } | - { type: 'object', properties: ObjectProps } -) - declare namespace factory { interface ValidationError { field: string @@ -78,11 +72,11 @@ declare interface Filter { } declare interface Factory { - (schema: ObjectSchema, options?: any): Validator> - (schema: T, options?: any): Validator + , R extends keyof T> (schema: ObjectSchema, options?: any): Validator> + (schema: T, options?: any): Validator - createFilter (schema: ObjectSchema, options?: any): Filter> - createFilter (schema: T, options?: any): Filter> + createFilter, R extends keyof T> (schema: ObjectSchema, options?: any): Filter> + createFilter (schema: T, options?: any): Filter> } declare const factory: Factory From c634f4b15837d3ce90829c47db8ab6915ab2c5c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20Unneb=C3=A4ck?= Date: Thu, 9 Aug 2018 21:56:34 +0100 Subject: [PATCH 4/6] Refactor to more verbose naming --- index.d.ts | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/index.d.ts b/index.d.ts index 79e4554..9c7b940 100644 --- a/index.d.ts +++ b/index.d.ts @@ -17,38 +17,38 @@ interface StringSchema { } interface AnyEnumSchema extends EnumSchema {} -interface EnumSchema { - enum: T[] +interface EnumSchema { + enum: Enum[] } interface AnyArraySchema extends ArraySchema {} -interface ArraySchema { +interface ArraySchema { type: 'array' - items: T + items: ItemSchema } interface AnyObjectSchema extends ObjectSchema, string> {} -interface ObjectSchema, R extends keyof T> { +interface ObjectSchema, Required extends keyof Properties> { additionalProperties?: boolean type: 'object' - properties: T - required: R[] + properties: Properties + required: Required[] } -interface ExtractedSchemaArray extends Array> {} +interface ExtractedSchemaArray extends Array> {} -declare type ExtractedSchemaObject = { - [K in keyof T]: (K extends R ? ExtractSchemaType : ExtractSchemaType | undefined) +declare type ExtractedSchemaObject = { + [Key in keyof Properties]: (Key extends Required ? ExtractSchemaType : ExtractSchemaType | undefined) } -declare type ExtractSchemaType = ( - Type extends EnumSchema ? T - : Type extends NullSchema ? null - : Type extends BooleanSchema ? boolean - : Type extends NumberSchema ? number - : Type extends StringSchema ? string - : Type extends ArraySchema ? ExtractedSchemaArray - : Type extends ObjectSchema ? ExtractedSchemaObject +declare type ExtractSchemaType = ( + Schema extends EnumSchema ? Enum + : Schema extends NullSchema ? null + : Schema extends BooleanSchema ? boolean + : Schema extends NumberSchema ? number + : Schema extends StringSchema ? string + : Schema extends ArraySchema ? ExtractedSchemaArray + : Schema extends ObjectSchema ? ExtractedSchemaObject : never ) @@ -72,11 +72,11 @@ declare interface Filter { } declare interface Factory { - , R extends keyof T> (schema: ObjectSchema, options?: any): Validator> - (schema: T, options?: any): Validator + , Required extends keyof Properties> (schema: ObjectSchema, options?: any): Validator> + (schema: Schema, options?: any): Validator - createFilter, R extends keyof T> (schema: ObjectSchema, options?: any): Filter> - createFilter (schema: T, options?: any): Filter> + createFilter, Required extends keyof Properties> (schema: ObjectSchema, options?: any): Filter> + createFilter (schema: Schema, options?: any): Filter> } declare const factory: Factory From feed73c1f1f3370c5f7c3bd3d0b73b87153dbf08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20Unneb=C3=A4ck?= Date: Thu, 9 Aug 2018 22:02:33 +0100 Subject: [PATCH 5/6] Improve type names --- index.d.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/index.d.ts b/index.d.ts index 9c7b940..2d234c2 100644 --- a/index.d.ts +++ b/index.d.ts @@ -35,20 +35,20 @@ interface ObjectSchema, Required ex required: Required[] } -interface ExtractedSchemaArray extends Array> {} +interface ArrayFromSchema extends Array> {} -declare type ExtractedSchemaObject = { - [Key in keyof Properties]: (Key extends Required ? ExtractSchemaType : ExtractSchemaType | undefined) +declare type ObjectFromSchema = { + [Key in keyof Properties]: (Key extends Required ? TypeFromSchema : TypeFromSchema | undefined) } -declare type ExtractSchemaType = ( +declare type TypeFromSchema = ( Schema extends EnumSchema ? Enum : Schema extends NullSchema ? null : Schema extends BooleanSchema ? boolean : Schema extends NumberSchema ? number : Schema extends StringSchema ? string - : Schema extends ArraySchema ? ExtractedSchemaArray - : Schema extends ObjectSchema ? ExtractedSchemaObject + : Schema extends ArraySchema ? ArrayFromSchema + : Schema extends ObjectSchema ? ObjectFromSchema : never ) @@ -61,7 +61,7 @@ declare namespace factory { } } -declare interface Validator> { +declare interface Validator> { (input: unknown, options?: any): input is Output errors: factory.ValidationError[] toJSON(): Schema @@ -75,8 +75,8 @@ declare interface Factory { , Required extends keyof Properties> (schema: ObjectSchema, options?: any): Validator> (schema: Schema, options?: any): Validator - createFilter, Required extends keyof Properties> (schema: ObjectSchema, options?: any): Filter> - createFilter (schema: Schema, options?: any): Filter> + createFilter, Required extends keyof Properties> (schema: ObjectSchema, options?: any): Filter> + createFilter (schema: Schema, options?: any): Filter> } declare const factory: Factory From 4c39294798cc90142cc56274e0bb20b8e752aaa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20Unneb=C3=A4ck?= Date: Thu, 9 Aug 2018 22:14:21 +0100 Subject: [PATCH 6/6] Tighten up generic input types --- index.d.ts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/index.d.ts b/index.d.ts index 2d234c2..da692e4 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,4 +1,5 @@ type AnySchema = NullSchema | BooleanSchema | NumberSchema | StringSchema | AnyEnumSchema | AnyArraySchema | AnyObjectSchema +type StringKeys = (keyof T) & string interface NullSchema { type: 'null' @@ -28,20 +29,20 @@ interface ArraySchema { } interface AnyObjectSchema extends ObjectSchema, string> {} -interface ObjectSchema, Required extends keyof Properties> { +interface ObjectSchema, Required extends StringKeys> { additionalProperties?: boolean type: 'object' properties: Properties required: Required[] } -interface ArrayFromSchema extends Array> {} +interface ArrayFromSchema extends Array> {} -declare type ObjectFromSchema = { +type ObjectFromSchema, Required extends StringKeys> = { [Key in keyof Properties]: (Key extends Required ? TypeFromSchema : TypeFromSchema | undefined) } -declare type TypeFromSchema = ( +type TypeFromSchema = ( Schema extends EnumSchema ? Enum : Schema extends NullSchema ? null : Schema extends BooleanSchema ? boolean @@ -61,21 +62,21 @@ declare namespace factory { } } -declare interface Validator> { +interface Validator> { (input: unknown, options?: any): input is Output errors: factory.ValidationError[] toJSON(): Schema } -declare interface Filter { +interface Filter { (input: Output, options?: any): Output } -declare interface Factory { - , Required extends keyof Properties> (schema: ObjectSchema, options?: any): Validator> +interface Factory { + , Required extends StringKeys> (schema: ObjectSchema, options?: any): Validator> (schema: Schema, options?: any): Validator - createFilter, Required extends keyof Properties> (schema: ObjectSchema, options?: any): Filter> + createFilter, Required extends StringKeys> (schema: ObjectSchema, options?: any): Filter> createFilter (schema: Schema, options?: any): Filter> }