Skip to content

Commit aefd048

Browse files
refactor(helper-functions): add isString and isNumber helper functions
- those helper functions also return true when a value was created using the constructor (new Number() or new String()) - refactor usage of typeof value to isString() or isNumber()
1 parent 862fcd9 commit aefd048

File tree

10 files changed

+78
-5
lines changed

10 files changed

+78
-5
lines changed

src/dynamo/expression/param-util.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*/
44
import * as DynamoDB from 'aws-sdk/clients/dynamodb'
55
import { isEmpty } from '../../helper/is-empty.function'
6+
import { isString } from '../../helper/is-string.function'
67
import { ConditionalParams } from '../operation-params.type'
78
import { resolveAttributeValueNameConflicts } from './functions/resolve-attribute-value-name-conflicts.function'
89
import { Expression } from './type/expression.type'
@@ -44,7 +45,7 @@ export function addExpression(
4445
}
4546

4647
const statement = params[expressionType]
47-
if (typeof statement === 'string' && statement !== '') {
48+
if (isString(statement) && statement !== '') {
4849
switch (expressionType) {
4950
case 'UpdateExpression':
5051
;(<any>params)[expressionType] = mergeUpdateExpressions(statement, nameSafeCondition.statement)

src/helper/get-tag.function.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { Tag } from './tag.enum'
2+
3+
/**
4+
* @return Returns the value (we call it tag) returned by function call `value.toString`,
5+
*/
6+
export function getTag(value: any): Tag | string {
7+
return Object.prototype.toString.call(value)
8+
}

src/helper/is-number.function.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { getTag } from './get-tag.function'
2+
import { Tag } from './tag.enum'
3+
4+
/**
5+
* @return Returns true for any value where typeof equals 'number' or an object created with Number constructor
6+
*/
7+
export function isNumber(value: any): boolean {
8+
return typeof value === 'number' || getTag(value) === Tag.NUMBER
9+
}

src/helper/is-number.spec.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { isNumber } from './is-number.function'
2+
3+
describe('is number', () => {
4+
it('should be a number', () => {
5+
expect(isNumber(3)).toBeTruthy()
6+
expect(isNumber(NaN)).toBeTruthy()
7+
expect(isNumber(Infinity)).toBeTruthy()
8+
// tslint:disable:no-construct
9+
expect(isNumber(new Number('2'))).toBeTruthy()
10+
expect(isNumber(new Number('myNumber'))).toBeTruthy()
11+
})
12+
13+
it('should not be a number', () => {
14+
expect(isNumber('a')).toBeFalsy()
15+
expect(isNumber({})).toBeFalsy()
16+
expect(isNumber([])).toBeFalsy()
17+
})
18+
})

src/helper/is-plain-object.function.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
// https://github.com/jonschlinkert/is-plain-object
2+
import { getTag } from './get-tag.function'
3+
import { Tag } from './tag.enum'
24

35
function isObject(val: any) {
46
return val != null && typeof val === 'object' && Array.isArray(val) === false
57
}
68

79
function isObjectObject(o: any): boolean {
8-
return isObject(o) === true && Object.prototype.toString.call(o) === '[object Object]'
10+
return isObject(o) === true && getTag(o) === Tag.OBJECT
911
}
1012

1113
export function isPlainObject(o: any): boolean {

src/helper/is-string.function.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { getTag } from './get-tag.function'
2+
import { Tag } from './tag.enum'
3+
4+
/**
5+
* @return Returns true for any value where typeof equals 'string' or an object created with String constructor
6+
*/
7+
export function isString(value: any): boolean {
8+
return typeof value === 'string' || getTag(value) === Tag.STRING
9+
}

src/helper/is-string.spec.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { isString } from './is-string.function'
2+
3+
describe('is string', () => {
4+
it('should be a string', () => {
5+
expect(isString('myValue')).toBeTruthy()
6+
// tslint:disable:no-construct
7+
expect(isString(new String('2'))).toBeTruthy()
8+
expect(isString(new String('someValue'))).toBeTruthy()
9+
})
10+
11+
it('should not be a string', () => {
12+
expect(isString(3)).toBeFalsy()
13+
expect(isString(true)).toBeFalsy()
14+
expect(isString({})).toBeFalsy()
15+
expect(isString([])).toBeFalsy()
16+
})
17+
})

src/helper/tag.enum.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/** used to compare with value returned by @link getTag(value), this is not a complete list only the one values used are defined */
2+
export enum Tag {
3+
OBJECT = '[object Object]',
4+
STRING = '[object String]',
5+
NUMBER = '[object Number]',
6+
}

src/mapper/for-type/number.mapper.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/**
22
* @module mapper
33
*/
4+
import { isNumber } from '../../helper/is-number.function'
45
import { NumberAttribute } from '../type/attribute.type'
56
import { MapperForType } from './base.mapper'
67

@@ -17,7 +18,7 @@ function numberFromDb(attributeValue: NumberAttribute): number {
1718
}
1819

1920
function numberToDb(modelValue: number): NumberAttribute | null {
20-
if (typeof modelValue !== 'number') {
21+
if (!isNumber(modelValue)) {
2122
throw new Error(`this mapper only support values of type number, value given: ${JSON.stringify(modelValue)}`)
2223
}
2324

src/mapper/util.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
* @module mapper
33
*/
44
import { PropertyMetadata } from '../decorator/metadata/property-metadata.model'
5+
import { isNumber } from '../helper/is-number.function'
6+
import { isString } from '../helper/is-string.function'
57
import { ModelConstructor } from '../model/model-constructor'
68
import { AttributeCollectionType, AttributeType } from './type/attribute-type.type'
79
import { AttributeValueType } from './type/attribute-value-type.type'
@@ -145,9 +147,9 @@ export function isSet(value: any): value is Set<any> {
145147
* @hidden
146148
*/
147149
export function detectType(value: any): AttributeType {
148-
if (typeof value === 'string') {
150+
if (isString(value)) {
149151
return 'S'
150-
} else if (typeof value === 'number') {
152+
} else if (isNumber(value)) {
151153
return 'N'
152154
} else if (isBinary(value)) {
153155
return 'B'

0 commit comments

Comments
 (0)