Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@finnair/v-validation

Package Overview
Dependencies
Maintainers
0
Versions
43
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@finnair/v-validation - npm Package Compare versions

Comparing version 7.0.0-alpha.3 to 7.0.0-alpha.4

dist/cjs/typing.d.ts

6

CHANGELOG.md

@@ -6,2 +6,8 @@ # Change Log

# [7.0.0-alpha.4](https://github.com/finnair/v-validation/compare/v7.0.0-alpha.3...v7.0.0-alpha.4) (2024-11-14)
### Features
- type guards to verify validator and existing type equality ([#119](https://github.com/finnair/v-validation/issues/119)) ([92699e7](https://github.com/finnair/v-validation/commit/92699e7c87e89246f92b24627278dfc57b9a128d))
# [7.0.0-alpha.3](https://github.com/finnair/v-validation/compare/v7.0.0-alpha.2...v7.0.0-alpha.3) (2024-11-11)

@@ -8,0 +14,0 @@

1

dist/cjs/index.d.ts

@@ -5,1 +5,2 @@ export * from './V.js';

export * from './objectValidatorBuilder.js';
export * from './typing.js';

@@ -21,1 +21,2 @@ "use strict";

__exportStar(require("./objectValidatorBuilder.js"), exports);
__exportStar(require("./typing.js"), exports);

3

dist/cjs/objectValidator.d.ts

@@ -17,2 +17,3 @@ import { Path } from "@finnair/path";

}
export type VInheritableType<V extends ObjectValidator<any, any>> = V extends ObjectValidator<any, infer Out> ? Out : unknown;
export interface ObjectModel<LocalType = unknown, InheritableType = unknown> {

@@ -47,3 +48,3 @@ /**

}
export declare class ObjectValidator<LocalType = unknown, InheritableType = unknown> extends Validator<LocalType, unknown> {
export declare class ObjectValidator<LocalType = unknown, InheritableType = LocalType> extends Validator<LocalType, unknown> {
readonly model: ObjectModel<LocalType, InheritableType>;

@@ -50,0 +51,0 @@ readonly properties: Properties;

@@ -39,3 +39,6 @@ "use strict";

this.localProperties = getPropertyValidators(model.localProperties);
this.nextValidator = nextValidators.length > 0 ? (0, validators_1.maybeCompositionOf)(...nextValidators) : undefined;
const next = nextValidators.length > 0 ? (0, validators_1.maybeCompositionOf)(...nextValidators) : undefined;
if (next) {
this.nextValidator = next;
}
if (model.localNext) {

@@ -42,0 +45,0 @@ if (!Array.isArray(model.localNext)) {

import { Validator } from "./validators.js";
import { ObjectValidator } from "./objectValidator.js";
type KeysOfType<T, SelectedType> = {
[key in keyof T]: SelectedType extends T[key] ? key : never;
}[keyof T];
type OptionalProperties<T> = Partial<Pick<T, KeysOfType<T, undefined>>>;
type RequiredProperties<T> = Omit<T, KeysOfType<T, undefined>>;
type UndefinedAsOptionalProperties<T> = RequiredProperties<T> & OptionalProperties<T>;
import { UndefinedAsOptionalProperties } from "./typing.js";
export declare class ObjectValidatorBuilder<Props, Next, LocalProps, LocalNext> {

@@ -24,8 +19,11 @@ private _extends;

}): ObjectValidatorBuilder<Props, Next, LocalProps & UndefinedAsOptionalProperties<X>, LocalNext>;
allowAdditionalProperties(allow: boolean): ObjectValidatorBuilder<Props & Record<string | number | symbol, unknown>, Next, LocalProps, LocalNext>;
additionalProperties<K extends keyof any, V>(keys: Validator<K>, values: Validator<V>): ObjectValidatorBuilder<Props & Record<K, V>, Next, LocalProps, LocalNext>;
next<NextOut>(validator: Validator<NextOut, Next extends {} ? Next : Props>): ObjectValidatorBuilder<Props, NextOut, LocalProps, LocalNext>;
localNext<NextOut>(validator: Validator<NextOut, LocalNext extends {} ? LocalNext : Next extends {} ? Next : Props & LocalProps>): ObjectValidatorBuilder<Props, Next, LocalProps, NextOut>;
build(): ObjectValidator<LocalNext extends {} ? LocalNext : Next extends {} ? Next : Props & LocalProps, Next extends {} ? Next : Props>;
allowAdditionalProperties(allow: boolean): ObjectValidatorBuilder<Props & {
[x: string]: unknown;
[x: number]: unknown;
[x: symbol]: unknown;
}, Next, LocalProps, LocalNext>;
additionalProperties<K extends keyof any, V>(keys: Validator<K>, values: Validator<V>): ObjectValidatorBuilder<Props & { [key in K]?: V; }, Next, LocalProps, LocalNext>;
next<NextOut extends {}>(validator: Validator<NextOut, Next extends {} ? Next : Props>): ObjectValidatorBuilder<Props, NextOut, LocalProps, LocalNext>;
localNext<NextOut extends {}>(validator: Validator<NextOut, LocalNext extends {} ? LocalNext : Next extends {} ? Next : Props & LocalProps>): ObjectValidatorBuilder<Props, Next, LocalProps, NextOut>;
build(): ObjectValidator<(Next extends {} ? Next : Props) & (LocalNext extends {} ? LocalNext : LocalProps), Next extends {} ? Next : Props>;
}
export {};

@@ -75,3 +75,3 @@ import { SchemaValidator, SchemaModel } from './schema.js';

}>(min: number, max: number) => SizeValidator<T>;
properties: <Key extends keyof any, Value>(keys: Validator<Key>, values: Validator<Value>) => ObjectValidator<Record<Key, Value>, unknown>;
properties: <Key extends keyof any, Value>(keys: Validator<Key>, values: Validator<Value>) => ObjectValidator<{ [key in Key]?: Value | undefined; }, { [key in Key]?: Value | undefined; }>;
allOf: AllOfParameters;

@@ -78,0 +78,0 @@ anyOf: <V extends [Validator<any>, ...Validator<any>[]]>(...validators: V) => AnyOfValidator<VType<V[any]>, unknown>;

@@ -5,1 +5,2 @@ export * from './V.js';

export * from './objectValidatorBuilder.js';
export * from './typing.js';

@@ -5,1 +5,2 @@ export * from './V.js';

export * from './objectValidatorBuilder.js';
export * from './typing.js';

@@ -17,2 +17,3 @@ import { Path } from "@finnair/path";

}
export type VInheritableType<V extends ObjectValidator<any, any>> = V extends ObjectValidator<any, infer Out> ? Out : unknown;
export interface ObjectModel<LocalType = unknown, InheritableType = unknown> {

@@ -47,3 +48,3 @@ /**

}
export declare class ObjectValidator<LocalType = unknown, InheritableType = unknown> extends Validator<LocalType, unknown> {
export declare class ObjectValidator<LocalType = unknown, InheritableType = LocalType> extends Validator<LocalType, unknown> {
readonly model: ObjectModel<LocalType, InheritableType>;

@@ -50,0 +51,0 @@ readonly properties: Properties;

@@ -35,3 +35,6 @@ import { AnyValidator, defaultViolations, HasValueValidator, isNullOrUndefined, isNumber, isString, maybeAllOfValidator, maybeCompositionOf, Validator, ValidatorFnWrapper, violationsOf, } from "./validators";

this.localProperties = getPropertyValidators(model.localProperties);
this.nextValidator = nextValidators.length > 0 ? maybeCompositionOf(...nextValidators) : undefined;
const next = nextValidators.length > 0 ? maybeCompositionOf(...nextValidators) : undefined;
if (next) {
this.nextValidator = next;
}
if (model.localNext) {

@@ -38,0 +41,0 @@ if (!Array.isArray(model.localNext)) {

import { Validator } from "./validators.js";
import { ObjectValidator } from "./objectValidator.js";
type KeysOfType<T, SelectedType> = {
[key in keyof T]: SelectedType extends T[key] ? key : never;
}[keyof T];
type OptionalProperties<T> = Partial<Pick<T, KeysOfType<T, undefined>>>;
type RequiredProperties<T> = Omit<T, KeysOfType<T, undefined>>;
type UndefinedAsOptionalProperties<T> = RequiredProperties<T> & OptionalProperties<T>;
import { UndefinedAsOptionalProperties } from "./typing.js";
export declare class ObjectValidatorBuilder<Props, Next, LocalProps, LocalNext> {

@@ -24,8 +19,11 @@ private _extends;

}): ObjectValidatorBuilder<Props, Next, LocalProps & UndefinedAsOptionalProperties<X>, LocalNext>;
allowAdditionalProperties(allow: boolean): ObjectValidatorBuilder<Props & Record<string | number | symbol, unknown>, Next, LocalProps, LocalNext>;
additionalProperties<K extends keyof any, V>(keys: Validator<K>, values: Validator<V>): ObjectValidatorBuilder<Props & Record<K, V>, Next, LocalProps, LocalNext>;
next<NextOut>(validator: Validator<NextOut, Next extends {} ? Next : Props>): ObjectValidatorBuilder<Props, NextOut, LocalProps, LocalNext>;
localNext<NextOut>(validator: Validator<NextOut, LocalNext extends {} ? LocalNext : Next extends {} ? Next : Props & LocalProps>): ObjectValidatorBuilder<Props, Next, LocalProps, NextOut>;
build(): ObjectValidator<LocalNext extends {} ? LocalNext : Next extends {} ? Next : Props & LocalProps, Next extends {} ? Next : Props>;
allowAdditionalProperties(allow: boolean): ObjectValidatorBuilder<Props & {
[x: string]: unknown;
[x: number]: unknown;
[x: symbol]: unknown;
}, Next, LocalProps, LocalNext>;
additionalProperties<K extends keyof any, V>(keys: Validator<K>, values: Validator<V>): ObjectValidatorBuilder<Props & { [key in K]?: V; }, Next, LocalProps, LocalNext>;
next<NextOut extends {}>(validator: Validator<NextOut, Next extends {} ? Next : Props>): ObjectValidatorBuilder<Props, NextOut, LocalProps, LocalNext>;
localNext<NextOut extends {}>(validator: Validator<NextOut, LocalNext extends {} ? LocalNext : Next extends {} ? Next : Props & LocalProps>): ObjectValidatorBuilder<Props, Next, LocalProps, NextOut>;
build(): ObjectValidator<(Next extends {} ? Next : Props) & (LocalNext extends {} ? LocalNext : LocalProps), Next extends {} ? Next : Props>;
}
export {};

@@ -75,3 +75,3 @@ import { SchemaValidator, SchemaModel } from './schema.js';

}>(min: number, max: number) => SizeValidator<T>;
properties: <Key extends keyof any, Value>(keys: Validator<Key>, values: Validator<Value>) => ObjectValidator<Record<Key, Value>, unknown>;
properties: <Key extends keyof any, Value>(keys: Validator<Key>, values: Validator<Value>) => ObjectValidator<{ [key in Key]?: Value | undefined; }, { [key in Key]?: Value | undefined; }>;
allOf: AllOfParameters;

@@ -78,0 +78,0 @@ anyOf: <V extends [Validator<any>, ...Validator<any>[]]>(...validators: V) => AnyOfValidator<VType<V[any]>, unknown>;

{
"name": "@finnair/v-validation",
"version": "7.0.0-alpha.3",
"version": "7.0.0-alpha.4",
"private": false,

@@ -51,5 +51,5 @@ "description": "V-validation core package",

"devDependencies": {
"@finnair/path": "^7.0.0-alpha.3"
"@finnair/path": "^7.0.0-alpha.4"
},
"gitHead": "6bb252ef025e936a14bc9f71e78804b61ea212e8"
"gitHead": "b0f6d3c6a456e19bcb50a78ccd6001661e46188b"
}

@@ -210,2 +210,3 @@ ![CI](https://github.com/finnair/v-validation/workflows/CI/badge.svg?branch=master)

- TypeScript native implementation
- Supports type inference that can be mixed with better readable custom types/interfaces

@@ -243,4 +244,40 @@ ## Pure Validation?

```
## Typing in Version >= 7
All built-in validators have input and output types. Typed ObjectValidators can be built with `V.objectType()`.
Since inferred types tend to get quite long and hard to read, you can also combine them with hand-written types.
### Validator Type
Use `VType<typeof validator>` to get the result type of `validator`.
Use `VInheritableType<typeof objectValidator> to get the inheritable type of `objectValidator: ObjectValidator<LocalType, Inheritabletype>`.
### Type Guards
When using custom interfaces it's good to verify that the validator is in sync with the interface. The
challenge is that TypeScript generic `extends` only verifies type compatibility, optional
properties do not count unless they are of conflicting type. For type-validator compatibility
we need to also consider optional properties and nested structure. For this there is two helper
types:
1. `ComparableType<T>` converts all optional properties to mandatory `Optional<T>` recursively.
2. `EqualTypes<A, B>` verifies that `A extends B` and `B extends A` and resolves to `true` if there's no error.
These can be used with `assertType` to verify type equality:
```typescript
interface MyInterface{
//...
}
const myInterfaceValidator = V.objectType()
.properties({
//...
})
.build();
// Use assertType function with EqualTypes and ComparableType to verify that myInterfaceValidator type is equal to MyInterface
assertType<EqualTypes<ComparableType<VType<typeof myInterfaceValidator>>, ComparableType<MyInterface>>>(true);
```
Why `assertType`? EqualTypes can also be used directly, but it needs to be tied to something (e.g. `type verified = Equaltypes<...>`),
but that something may then cause "is declared but never used" -error.
## Combining Validators

@@ -294,3 +331,3 @@

.localProperties({
type: V.hasValue('Bike' as const),
type: V.hasValue<'Bike'>('Bike'), // Another way of enforcing literal type
})

@@ -399,4 +436,3 @@ .build();

Polymorphic schemas are recursive in nature: 1) a child needs to know it's parents so that it may extend them and 2) unless the type information is natively bound to
the object being validated, the parent needs to know it's children so that it may dispatch the validation to the correct child. As (direct) cyclic references are not possible, SchemaValidator is created with a callback function that supports referencing other models within the schema by name
even before they are defined:
the object being validated, the parent needs to know it's children so that it may dispatch the validation to the correct child. As (direct) cyclic references are not possible, SchemaValidator is created with a callback function that supports referencing other models within the schema by name even before they are defined:

@@ -468,14 +504,24 @@ 1. An object may extend other models by simply referencing them by name.

Recursive model has a cyclic reference to itself. While a model cannot reference itself
before it's declared, we can wrap the call within a validator function:
Recursive model has a cyclic reference to itself. While a model cannot reference itself before it's declared,
we can wrap the call within a validator function. Type inference also cannot infer type from itself so we need
to define the target interface separately.
```typescript
// { head: 'first value', tail: { head: 'second value', tail: { head: 'last value' } } }
const list = V.object({
properties: {
first: V.any(),
// Instead of recursive model, we have recursive call
next: V.optional(V.fn((value: any, path: Path, ctx: ValidationContext) => list.validatePath(value, path, ctx))),
},
});
interface RecursiveModel {
first: string;
next?: RecursiveModel;
}
// Typed placeholder for the recursive validator
let recursion: ObjectValidator<RecursiveModel, RecursiveModel>;
const validator = V.objectType()
.properties({
first: V.string(),
next: V.optionalStrict(V.fn((value: any, path: Path, ctx: ValidationContext) => recursion.validatePath(value, path, ctx))),
})
.build();
recursion = validator;
// Verify that validator matches RecursiveModel
assertType<EqualTypes<ComparableType<VType<typeof validator>>, ComparableType<RecursiveModel>>>(true);
```

@@ -482,0 +528,0 @@

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc