Skip to content

Commit

Permalink
Merge branch 'release/0.5.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
charlespascoe committed Jan 9, 2018
2 parents 842bda8 + a3e1f1d commit aaff589
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 6 deletions.
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,14 @@ const barValidator: Validator<IBar> = extendValidator(fooValidator, {
```

### validate ###
`function validate<T>(arg: any, validator: Validator<T>): Validated<T>`
`function validate<T>(arg: any, validator: Validator<T>, options?: IValidationOptions): Validated<T>`

Checks that `arg` conforms to the type `T` using the given `validator`. Returns an object that conforms to `T` or throws an error.

The third argument is an optional object of options:

- `allowAdditionalProperties: boolean` - If false, an error is thrown if there are any properties in addition to the ones defined in the validator. Defaults to `true`, which removes additional properties from the result.

### optional ###
Used when the property may not present on the object, or its value is undefined. Example:

Expand Down Expand Up @@ -422,7 +426,7 @@ validate({

### Handling Validation Errors ###

Errors will always be of the type `ValidationErrorCollection`, which has a property `error: ValidationError[]`.
Errors will always be of the type `ValidationErrorCollection`, which has a property `errors: ValidationError[]`.

The `ValidationError` type has a number of useful properties:

Expand Down
30 changes: 28 additions & 2 deletions lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export class KeyPathNode extends PathNode {
}

public toString(): string {
if (/^[$a-z_]+$/i.test(this.key)) {
if (/^[$a-z_][$a-z0-9_]*$/i.test(this.key)) {
return `.${this.key}`;
} else {
return `['${this.key.replace('\\', '\\\\').replace("'", "\\'")}']`;
Expand Down Expand Up @@ -95,14 +95,30 @@ export class ValidationErrorCollection {
}


export function validate<T>(arg: any, validator: Validator<T>): Validated<T> {
export interface IValidationOptions {
allowAdditionalProperties?: boolean;
}


export function validate<T>(arg: any, validator: Validator<T>, options: IValidationOptions = {}): Validated<T> {
const {
allowAdditionalProperties = true
} = options;

if (typeof arg !== 'object') throw new ValidationErrorCollection(new ValidationError('NOT_OBJECT', `Expected object, got ${typeof arg}`));

const result: {[key in keyof T]?: T[key]} = {};

let validationErrorCollection: ValidationErrorCollection | null = null;

const validatedProperties = Object.keys(arg).reduce((validatedProperties, key) => {
validatedProperties[key] = false;
return validatedProperties;
}, {} as {[key: string]: boolean});

for (const key in validator) {
validatedProperties[key] = true;

try {
result[key] = validator[key](arg[key]);
} catch (err) {
Expand All @@ -114,6 +130,16 @@ export function validate<T>(arg: any, validator: Validator<T>): Validated<T> {
}
}

if (!allowAdditionalProperties && !Object.keys(validatedProperties).every(key => validatedProperties[key])) {
if (validationErrorCollection === null) {
validationErrorCollection = new ValidationErrorCollection();
}

validationErrorCollection.errors.push(
new ValidationError('UNEXPECTED_ADDITIONAL_PROPERTIES', `Unexpected additional properties: ${Object.keys(validatedProperties).filter(key => !validatedProperties[key]).join(', ')}`)
);
}

if (validationErrorCollection !== null) throw validationErrorCollection;

return result as Validated<T>;
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "validate-interface",
"version": "0.5.0",
"version": "0.5.1",
"description": "Validate Objects Against TypeScript Interfaces",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down

0 comments on commit aaff589

Please sign in to comment.