Skip to content

Commit 0f445ca

Browse files
committed
improv(commons): expand type utils functions
1 parent 5798ee8 commit 0f445ca

File tree

6 files changed

+525
-173
lines changed

6 files changed

+525
-173
lines changed

packages/commons/package.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,21 @@
4040
"default": "./lib/esm/index.js"
4141
}
4242
},
43+
"./typeutils": {
44+
"import": "./lib/esm/typeUtils.js",
45+
"require": "./lib/cjs/typeUtils.js"
46+
},
4347
"./types": {
4448
"import": "./lib/esm/types/index.js",
4549
"require": "./lib/cjs/types/index.js"
4650
}
4751
},
4852
"typesVersions": {
4953
"*": {
54+
"typeutils": [
55+
"lib/cjs/typeUtils.d.ts",
56+
"lib/esm/typeUtils.d.ts"
57+
],
5058
"types": [
5159
"lib/cjs/types/index.d.ts",
5260
"lib/esm/types/index.d.ts"

packages/commons/src/guards.ts

Lines changed: 0 additions & 52 deletions
This file was deleted.

packages/commons/src/index.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
1-
export { isRecord, isString, isTruthy, isNullOrUndefined } from './guards.js';
1+
export {
2+
isRecord,
3+
isString,
4+
isNumber,
5+
isIntegerNumber,
6+
isTruthy,
7+
isNull,
8+
isNullOrUndefined,
9+
getType,
10+
isStrictEqual,
11+
} from './typeUtils.js';
212
export { Utility } from './Utility.js';
313
export { EnvironmentVariablesService } from './config/EnvironmentVariablesService.js';
414
export { addUserAgentMiddleware, isSdkClient } from './awsSdkUtils.js';

packages/commons/src/typeUtils.ts

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
/**
2+
* Returns true if the passed value is a record (object).
3+
*
4+
* @param value The value to check
5+
*/
6+
const isRecord = (value: unknown): value is Record<string, unknown> => {
7+
return (
8+
Object.prototype.toString.call(value) === '[object Object]' &&
9+
!Object.is(value, null)
10+
);
11+
};
12+
13+
/**
14+
* Check if a value is a string.
15+
*
16+
* @param value The value to check
17+
*/
18+
const isString = (value: unknown): value is string => {
19+
return typeof value === 'string';
20+
};
21+
22+
/**
23+
* Check if a value is a number.
24+
*
25+
* @param value The value to check
26+
*/
27+
const isNumber = (value: unknown): value is number => {
28+
return typeof value === 'number';
29+
};
30+
31+
/**
32+
* Check if a value is an integer number.
33+
*
34+
* @param value The value to check
35+
*/
36+
const isIntegerNumber = (value: unknown): value is number => {
37+
return isNumber(value) && Number.isInteger(value);
38+
};
39+
40+
/**
41+
* Check if a value is truthy.
42+
*
43+
* @param value The value to check
44+
*/
45+
const isTruthy = (value: unknown): boolean => {
46+
if (isString(value)) {
47+
return value !== '';
48+
} else if (isNumber(value)) {
49+
return value !== 0;
50+
} else if (typeof value === 'boolean') {
51+
return value;
52+
} else if (Array.isArray(value)) {
53+
return value.length > 0;
54+
} else if (isRecord(value)) {
55+
return Object.keys(value).length > 0;
56+
} else {
57+
return false;
58+
}
59+
};
60+
61+
/**
62+
* Check if a value is null.
63+
*
64+
* @param value The value to check
65+
*/
66+
const isNull = (value: unknown): value is null => {
67+
return Object.is(value, null);
68+
};
69+
70+
/**
71+
* Check if a value is null or undefined.
72+
*
73+
* @param value The value to check
74+
*/
75+
const isNullOrUndefined = (value: unknown): value is null | undefined => {
76+
return isNull(value) || Object.is(value, undefined);
77+
};
78+
79+
/**
80+
* Get the type of a value as a string.
81+
*
82+
* @param value The value to check
83+
*/
84+
const getType = (value: unknown): string => {
85+
if (Array.isArray(value)) {
86+
return 'array';
87+
} else if (isRecord(value)) {
88+
return 'object';
89+
} else if (isString(value)) {
90+
return 'string';
91+
} else if (isNumber(value)) {
92+
return 'number';
93+
} else if (typeof value === 'boolean') {
94+
return 'boolean';
95+
} else if (isNull(value)) {
96+
return 'null';
97+
} else {
98+
return 'unknown';
99+
}
100+
};
101+
102+
/**
103+
* Compare two arrays for strict equality.
104+
*
105+
* @param left The left array to compare
106+
* @param right The right array to compare
107+
*/
108+
const areArraysEqual = (left: unknown[], right: unknown[]): boolean => {
109+
if (left.length !== right.length) {
110+
return false;
111+
}
112+
113+
return left.every((value, i) => isStrictEqual(value, right[i]));
114+
};
115+
116+
/**
117+
* Compare two records for strict equality.
118+
*
119+
* @param left The left record to compare
120+
* @param right The right record to compare
121+
*/
122+
const areRecordsEqual = (
123+
left: Record<string, unknown>,
124+
right: Record<string, unknown>
125+
): boolean => {
126+
const leftKeys = Object.keys(left);
127+
const rightKeys = Object.keys(right);
128+
129+
if (leftKeys.length !== rightKeys.length) {
130+
return false;
131+
}
132+
133+
return leftKeys.every((key) => isStrictEqual(left[key], right[key]));
134+
};
135+
136+
/**
137+
* Check if two unknown values are strictly equal.
138+
*
139+
* If the values are arrays, then each element is compared, regardless of
140+
* order. If the values are objects, then each key and value from left
141+
* is compared to the corresponding key and value from right. If the
142+
* values are primitives, then they are compared using strict equality.
143+
*
144+
* @param left Left side of strict equality comparison
145+
* @param right Right side of strict equality comparison
146+
*/
147+
const isStrictEqual = (left: unknown, right: unknown): boolean => {
148+
if (left === right) {
149+
return true;
150+
}
151+
152+
if (typeof left !== typeof right) {
153+
return false;
154+
}
155+
156+
if (Array.isArray(left) && Array.isArray(right)) {
157+
return areArraysEqual(left, right);
158+
}
159+
160+
if (isRecord(left) && isRecord(right)) {
161+
return areRecordsEqual(left, right);
162+
}
163+
164+
return false;
165+
};
166+
167+
export {
168+
isRecord,
169+
isString,
170+
isNumber,
171+
isIntegerNumber,
172+
isTruthy,
173+
isNull,
174+
isNullOrUndefined,
175+
getType,
176+
isStrictEqual,
177+
};

packages/commons/tests/unit/guards.test.ts

Lines changed: 0 additions & 120 deletions
This file was deleted.

0 commit comments

Comments
 (0)