-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added more types, added tests and upgraded libraries
- Loading branch information
1 parent
b6dba84
commit bfe500b
Showing
7 changed files
with
239 additions
and
48 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,3 +2,4 @@ node_modules | |
.idea | ||
dist | ||
package-lock.json | ||
coverage |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
src/ | ||
.babelrc | ||
.npmignore | ||
LICENSE | ||
.github | ||
.idea | ||
coverage | ||
README.md | ||
webpack.config.js |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import strongTyped, {Types} from "./index"; | ||
|
||
const fn = (val) => strongTyped([Types.STRING], (a) => { console.log(a) }); | ||
const fn_falsy = (val) => strongTyped(['asdf'], (a) => { console.log(a) }); | ||
const testFn = (a) => { console.log(a) }; | ||
|
||
test('valid string input', () => { | ||
expect(fn("string")).toBeTruthy(); | ||
}); | ||
|
||
test('invalid type declared', () => { | ||
expect(fn_falsy(1)).toBeTruthy(); | ||
}); | ||
|
||
test("parameter number validation error message", () => { | ||
const myFunc = strongTyped([Types.STRING], testFn); | ||
expect(() => {myFunc()}).toThrow(Error); | ||
expect(() => {myFunc()}).toThrow("Function testFn expects 1 arguments, instead only 0 parameter(s) passed in."); | ||
}); | ||
|
||
test("extra parameter types number validation error thrown", () => { | ||
expect(() => {strongTyped([Types.STRING, Types.STRING], testFn)}).toThrow(Error); | ||
expect(() => {strongTyped([Types.STRING, Types.STRING], testFn)}).toThrow("Function testFn has 1 argument(s) and only 2 type(s) defined."); | ||
}); | ||
|
||
test("parameter types number validation error message", () => { | ||
const myFunc = strongTyped([Types.STRING], testFn); | ||
expect(() => {strongTyped([], testFn)}).toThrow(Error); | ||
expect(() => {myFunc()}).toThrow("Function testFn expects 1 arguments, instead only 0 parameter(s) passed in."); | ||
}); | ||
|
||
test("unsupported parameter types validation error message", () => { | ||
const myFunc = strongTyped(["Blah"], testFn); | ||
expect(() => {myFunc("test")}).toThrow(Error); | ||
expect(() => {myFunc("test")}).toThrow("Unsupported type found in argument 1 for function testFn, supported types are any,date,integer,bigint,boolean,decimal,string,object,function,array,set,map"); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,83 +1,101 @@ | ||
const strongTyped = (types, fn) => { | ||
|
||
const ANY = 'any'; | ||
const DATE = 'date'; | ||
const INTEGER = 'integer'; | ||
const BOOLEAN = 'boolean'; | ||
const DECIMAL = 'decimal'; | ||
const STRING = 'string'; | ||
const OBJECT = 'object'; | ||
const FN = 'function'; | ||
const ARRAY = 'array'; | ||
|
||
const staticTypes = [ANY, DATE, INTEGER, BOOLEAN, DECIMAL, STRING, OBJECT, FN, | ||
ARRAY]; | ||
|
||
if (types.length !== fn.length) { | ||
throw new Error(`Function has ${fn.length} argument(s) and only ${types.length} type(s) defined`); | ||
throw new Error(`Function ${fn.name} has ${fn.length} argument(s) and only ${types.length} type(s) defined.`); | ||
} | ||
|
||
let isValidType = (value, type, argIndex) => { | ||
const isValidType = (value, type, argIndex) => { | ||
switch (type.toLowerCase()) { | ||
case ANY : | ||
return true; | ||
case DATE : | ||
if (typeof value === OBJECT && value instanceof DATE) { | ||
case Types.ANY : | ||
break; | ||
case Types.DATE : | ||
if (typeof value === Types.OBJECT && value instanceof Types.DATE) { | ||
return true; | ||
} | ||
break; | ||
case BOOLEAN : | ||
if (typeof value === BOOLEAN) { | ||
case Types.BOOLEAN : | ||
if (typeof value === Types.BOOLEAN) { | ||
return true; | ||
} | ||
break; | ||
case STRING : | ||
if (typeof value === STRING) { | ||
case Types.STRING : | ||
if (typeof value === Types.STRING) { | ||
return true; | ||
} | ||
break; | ||
case INTEGER : | ||
case Types.BIG_INT: | ||
if (typeof value === Types.BIG_INT) { | ||
return true; | ||
} | ||
break; | ||
case Types.INTEGER : | ||
if (typeof value === 'number' && Number.isInteger(value)) { | ||
return true; | ||
} | ||
break; | ||
case DECIMAL : | ||
if (typeof value === 'number' && !Number.isInteger(value)) { | ||
case Types.DECIMAL : | ||
if (typeof value === 'number' && !Number.isInteger(value) && !isNaN(value)) { | ||
return true; | ||
} | ||
break; | ||
case Types.OBJECT : | ||
if (typeof value === Types.OBJECT) { | ||
return true; | ||
} | ||
break; | ||
case OBJECT : | ||
if (typeof value === OBJECT) { | ||
case Types.FN : | ||
if (typeof value === Types.FN) { | ||
return true; | ||
} | ||
break; | ||
case FN : | ||
if (typeof value === FN) { | ||
case Types.ARRAY : | ||
if (typeof value === Types.OBJECT && Array.isArray(value)) { | ||
return true; | ||
} | ||
break; | ||
case ARRAY : | ||
if (typeof value === OBJECT && Array.isArray(value)) { | ||
case Types.SET : | ||
if (typeof value === "object" && value instanceof Set) { | ||
return true; | ||
} | ||
break; | ||
case Types.MAP : | ||
if (typeof value === "object" && value instanceof Map) { | ||
return true; | ||
} | ||
break; | ||
default : | ||
throw new Error(`Unsupported type found in argument ${argIndex + 1}, supported types are ${staticTypes.toString()}`); | ||
throw new Error(`Unsupported type found in argument ${argIndex + 1} for function ${fn.name}, supported types are ${Object.values(Types)}`); | ||
} | ||
throw new Error(`Expected argument ${argIndex + 1} to be of type '${type}'`); | ||
throw new Error(`Function ${fn.name} expected argument ${argIndex + 1} to be of type '${type}'`); | ||
}; | ||
|
||
return (...args) => { | ||
if (types.length !== args.length) { | ||
throw new Error(`Function expects ${fn.length} arguments, instead only ${args.length} parameter(s) passed in.`); | ||
throw new Error(`Function ${fn.name} expects ${fn.length} arguments, instead only ${args.length} parameter(s) passed in.`); | ||
} | ||
|
||
for (let i = 0; i < args.length; i++) { | ||
isValidType(args[i], types[i], i) | ||
isValidType(args[i], types[i], i); | ||
} | ||
|
||
return fn(...args); | ||
} | ||
}; | ||
|
||
export const Types = { | ||
ANY: 'any', | ||
DATE: 'date', | ||
INTEGER: 'integer', | ||
BIG_INT: 'bigint', | ||
BOOLEAN: 'boolean', | ||
DECIMAL: 'decimal', | ||
STRING: 'string', | ||
OBJECT: 'object', | ||
FN: 'function', | ||
ARRAY: 'array', | ||
SET: 'set', | ||
MAP: 'map' | ||
}; | ||
Object.freeze(Types); | ||
|
||
export default strongTyped; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
import strongTyped, {Types} from "./index"; | ||
|
||
const testFn = (a) => { console.log(a) }; | ||
|
||
test("Any input", () => { | ||
const myFunc = strongTyped([Types.ANY], testFn); | ||
expect(() => {myFunc("1")}).toBeTruthy(); | ||
expect(() => {myFunc(1)}).toBeTruthy(); | ||
expect(() => {myFunc(1.0)}).toBeTruthy(); | ||
expect(() => {myFunc([])}).toBeTruthy(); | ||
expect(() => {myFunc({})}).toBeTruthy(); | ||
expect(() => {myFunc(new Set())}).toBeTruthy(); | ||
expect(() => {myFunc(new Date())}).toBeTruthy(); | ||
}); | ||
|
||
test("String input", () => { | ||
const myFunc = strongTyped([Types.STRING], testFn); | ||
expect(() => {myFunc("1")}).toBeTruthy(); | ||
|
||
expect(() => {myFunc(1)}).toThrow(Error); | ||
expect(() => {myFunc(1)}).toThrow("Function testFn expected argument 1 to be of type 'string'"); | ||
}); | ||
|
||
test("Big integer input", () => { | ||
const myFunc = strongTyped([Types.BIG_INT], testFn); | ||
//expect(() => {myFunc(9007199254740991n)}).toBeTruthy(); | ||
expect(() => {myFunc(BigInt(9007199254740991))}).toBeTruthy(); | ||
expect(() => {myFunc(BigInt("0x1fffffffffffff"))}).toBeTruthy(); | ||
expect(() => {myFunc(BigInt("0b11111111111111111111111111111111111111111111111111111"))}).toBeTruthy(); | ||
|
||
expect(() => {myFunc("test")}).toThrow(Error); | ||
expect(() => {myFunc("test")}).toThrow("Function testFn expected argument 1 to be of type 'bigint'"); | ||
}); | ||
|
||
test("Array input", () => { | ||
const myFunc = strongTyped([Types.ARRAY], testFn); | ||
expect(() => {myFunc(['Apple', 'Banana'])}).toBeTruthy(); | ||
expect(() => {myFunc([1, 2])}).toBeTruthy(); | ||
expect(() => {myFunc([[1], [2]])}).toBeTruthy(); | ||
|
||
|
||
expect(() => {myFunc(new Date())}).toThrow(Error); | ||
expect(() => {myFunc("test")}).toThrow(Error); | ||
expect(() => {myFunc("test")}).toThrow("Function testFn expected argument 1 to be of type 'array'"); | ||
}); | ||
|
||
test("Boolean input", () => { | ||
const myFunc = strongTyped([Types.BOOLEAN], testFn); | ||
expect(() => {myFunc(true)}).toBeTruthy(); | ||
expect(() => {myFunc(false)}).toBeTruthy(); | ||
expect(() => {myFunc(0)}).toBeTruthy(); | ||
expect(() => {myFunc(1)}).toBeTruthy(); | ||
|
||
expect(() => {myFunc("test")}).toThrow(Error); | ||
expect(() => {myFunc("test")}).toThrow("Function testFn expected argument 1 to be of type 'boolean'"); | ||
}); | ||
|
||
test("Date input", () => { | ||
const myFunc = strongTyped([Types.DATE], testFn); | ||
expect(() => {myFunc(Date.now())}).toBeTruthy(); | ||
expect(() => {myFunc(Date.UTC())}).toBeTruthy(); | ||
expect(() => {myFunc(new Date())}).toBeTruthy(); | ||
expect(() => {myFunc(new Date('December 17, 1995 03:24:00'))}).toBeTruthy(); | ||
expect(() => {myFunc(new Date(new Date('1995-12-17T03:24:00')))}).toBeTruthy(); | ||
|
||
expect(() => {myFunc({})}).toThrow(Error); | ||
expect(() => {myFunc("test")}).toThrow(Error); | ||
expect(() => {myFunc("test")}).toThrow("Function testFn expected argument 1 to be of type 'date'"); | ||
}); | ||
|
||
test("Decimal input", () => { | ||
const myFunc = strongTyped([Types.DECIMAL], testFn); | ||
expect(() => {myFunc(2.333)}).toBeTruthy(); | ||
expect(() => {myFunc(Number.EPSILON)}).toBeTruthy(); | ||
|
||
expect(() => {myFunc(1)}).toThrow(Error); | ||
expect(() => {myFunc(Number.NaN)}).toThrow(Error); | ||
expect(() => {myFunc("test")}).toThrow(Error); | ||
expect(() => {myFunc("test")}).toThrow("Function testFn expected argument 1 to be of type 'decimal'"); | ||
}); | ||
|
||
test("Integer input", () => { | ||
const myFunc = strongTyped([Types.INTEGER], testFn); | ||
expect(() => {myFunc(123)}).toBeTruthy(); | ||
expect(() => {myFunc(Number.MAX_SAFE_INTEGER)}).toBeTruthy(); | ||
|
||
expect(() => {myFunc(Number.EPSILON)}).toThrow(Error); | ||
expect(() => {myFunc(Number.NaN)}).toThrow(Error); | ||
expect(() => {myFunc("test")}).toThrow(Error); | ||
expect(() => {myFunc("test")}).toThrow("Function testFn expected argument 1 to be of type 'integer'"); | ||
}); | ||
|
||
test("Function input", () => { | ||
const myFunc = strongTyped([Types.FN], testFn); | ||
expect(() => {myFunc(testFn("test"))}).toBeTruthy(); | ||
|
||
expect(() => {myFunc("test")}).toThrow(Error); | ||
expect(() => {myFunc("test")}).toThrow("Function testFn expected argument 1 to be of type 'function'"); | ||
}); | ||
|
||
test("Object input", () => { | ||
const myFunc = strongTyped([Types.OBJECT], testFn); | ||
expect(() => {myFunc(testFn({}))}).toBeTruthy(); | ||
|
||
expect(() => {myFunc("test")}).toThrow(Error); | ||
expect(() => {myFunc("test")}).toThrow("Function testFn expected argument 1 to be of type 'object'"); | ||
}); | ||
|
||
test("Set input", () => { | ||
const myFunc = strongTyped([Types.SET], testFn); | ||
expect(() => {myFunc(testFn(new Set()))}).toBeTruthy(); | ||
expect(() => {myFunc(testFn(new Set([1, 2, 3, 4])))}).toBeTruthy(); | ||
|
||
expect(() => {myFunc({})}).toThrow(Error); | ||
expect(() => {myFunc("test")}).toThrow(Error); | ||
expect(() => {myFunc("test")}).toThrow("Function testFn expected argument 1 to be of type 'set'"); | ||
}); | ||
|
||
test("Map input", () => { | ||
const myFunc = strongTyped([Types.MAP], testFn); | ||
expect(() => {myFunc(testFn(new Map()))}).toBeTruthy(); | ||
|
||
expect(() => {myFunc({})}).toThrow(Error); | ||
expect(() => {myFunc("test")}).toThrow(Error); | ||
expect(() => {myFunc("test")}).toThrow("Function testFn expected argument 1 to be of type 'map'"); | ||
}); | ||
|