Skip to content
Open
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
9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"description": "Validate JSON objects with TypeScript-like interface specifications.",
"main": "lib/interface-validator.js",
"scripts": {
"pretest": "tsc",
"test": "mocha",
"prepublish": "tsc"
},
Expand All @@ -23,14 +24,14 @@
},
"homepage": "https://github.com/hanlindev/interface-validator#readme",
"dependencies": {
"@types/lodash": "^4.14.62",
"@types/lodash": "^4.14.95",
"lodash": "^4.17.4"
},
"devDependencies": {
"@types/chai": "^3.4.35",
"@types/mocha": "^2.2.40",
"@types/chai": "^3.5.2",
"@types/mocha": "^2.2.47",
"chai": "^3.5.0",
"mocha": "^3.2.0"
"mocha": "^3.5.3"
},
"types": "./lib/interface-validator.d.ts"
}
11 changes: 10 additions & 1 deletion src/interface-validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export type PrimitiveTypes =
'string!' | 'string'
| 'number' | 'number!'
| 'boolean' | 'boolean!'
| 'object';
| 'object' | object[];

/**
* The key must be a valid variable name with an optional trailing question
Expand Down Expand Up @@ -58,6 +58,15 @@ export function getMismatchedFields(
return (isOptional) ? [] : [valueKey];
}

if (_.isArray(fieldSpecs[specName])) {
return values[valueKey].map((arrayValue, index) => {
return getMismatchedFields(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part can be modified to support primitive arrays. I imagine the way to specify primitive arrays to be like ['number'] or ['boolean'], following your test example. Then to add primitive support here, you need to:

  1. Extract the primitive check from Line 76 to Line 111 to a function accepting the primitive type and a value.
  2. Check here if the fieldSpecs[specName][0] is a string, indicating a primitive type. If it is, use the extracted function to check. Otherwise, call getMismatchedFields.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, in the extracted function, check if the primitive type is one of the expected types, i.e. the string name is correct. You can throw a TypeError if it isn't. This is to provide runtime safety.

arrayValue,
fieldSpecs[specName][0] as Interface,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a array out-of-bound guard here. If fieldSpecs[specName][0] is undefined, throw a TypeError here. The message can be a JSON.stringified string of the whole fieldSpecs and the specName to help with debugging.

).map((name) => `${valueKey}[${index}].${name}`);
}).filter((e) => e.length > 0)
}

return getMismatchedFields(
values[valueKey],
fieldSpecs[specName] as Interface,
Expand Down
20 changes: 20 additions & 0 deletions src/test/test-interface-validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ describe('interface-validator getMismatchedFields', () => {
},
string: 'nested str',
},
objectArray: [{
string: 'str',
number: 0,
},{
string: 'str'
}],
castToNumber: '123',
castToNumberFail: 'one',
castToBoolean: 'true',
Expand Down Expand Up @@ -131,4 +137,18 @@ describe('interface-validator getMismatchedFields', () => {
expect(getMismatchedFields(tested, subSpecs)).to.be.empty;
});
});

describe('nested array interface', () => {
const specs: Interface = {
number: 'number',
objectArray: [{
string: 'string',
'number?': 'number'
}]
};

it('returns empty array when all matched', () => {
expect(getMismatchedFields(tested, specs)).to.be.empty;
})
});
});