Skip to content

Commit 5abe676

Browse files
committed
fix: reducing use of "any"
1 parent 823634b commit 5abe676

File tree

2 files changed

+89
-72
lines changed

2 files changed

+89
-72
lines changed
Lines changed: 89 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
/* eslint-disable @typescript-eslint/no-explicit-any */
2-
31
import { InterpolatableTranslationObject } from './translate.service';
42

53
/**
@@ -15,38 +13,43 @@ import { InterpolatableTranslationObject } from './translate.service';
1513
* @param o2 Object or value to compare.
1614
* @returns true if arguments are equal.
1715
*/
18-
export function equals(o1: any, o2: any): boolean {
16+
export function equals(o1: unknown, o2: unknown): boolean {
1917
if (o1 === o2) return true;
2018
if (o1 === null || o2 === null) return false;
2119
if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN
20+
2221
const t1 = typeof o1, t2 = typeof o2;
23-
let length: number, key: any, keySet: any;
22+
let length: number;
23+
2424
if (t1 == t2 && t1 == 'object') {
2525
if (Array.isArray(o1)) {
2626
if (!Array.isArray(o2)) return false;
2727
if ((length = o1.length) == o2.length) {
28-
for (key = 0; key < length; key++) {
28+
for (let key = 0; key < length; key++) {
2929
if (!equals(o1[key], o2[key])) return false;
3030
}
3131
return true;
3232
}
33-
} else {
33+
}
34+
else {
3435
if (Array.isArray(o2)) {
3536
return false;
3637
}
37-
keySet = Object.create(null);
38-
for (key in o1) {
39-
if (!equals(o1[key], o2[key])) {
40-
return false;
38+
if(isDict(o1) && isDict(o2)) {
39+
const keySet = Object.create(null);
40+
for (const key in o1) {
41+
if (!equals(o1[key], o2[key])) {
42+
return false;
43+
}
44+
keySet[key] = true;
4145
}
42-
keySet[key] = true;
43-
}
44-
for (key in o2) {
45-
if (!(key in keySet) && typeof o2[key] !== 'undefined') {
46-
return false;
46+
for (const key in o2) {
47+
if (!(key in keySet) && typeof o2[key] !== 'undefined') {
48+
return false;
49+
}
4750
}
51+
return true;
4852
}
49-
return true;
5053
}
5154
}
5255
return false;
@@ -56,61 +59,59 @@ export function isDefinedAndNotNull<T>(value: T | null | undefined): value is T
5659
return typeof value !== 'undefined' && value !== null;
5760
}
5861

62+
export function isDefined<T>(value: T | null | undefined): value is (T | null) {
63+
return value !== undefined;
64+
}
5965

60-
export function isDict(value: any): value is InterpolatableTranslationObject {
66+
export function isDict(value: unknown): value is InterpolatableTranslationObject {
6167
return isObject(value) && !isArray(value) && value !== null;
6268
}
6369

64-
65-
export function isObject(value: any): value is Record<string, any> {
70+
export function isObject(value: unknown): value is Record<string, unknown> {
6671
return typeof value === 'object' && value !== null;
6772
}
6873

69-
export function isArray(value: any): value is any[] {
74+
export function isArray(value: unknown): value is unknown[] {
7075
return Array.isArray(value);
7176
}
7277

73-
export function isString(value: any): value is string {
78+
export function isString(value: unknown): value is string {
7479
return typeof value === 'string';
7580
}
7681

77-
export function isFunction(value: any): boolean {
82+
export function isFunction(value: unknown): boolean {
7883
return typeof value === "function"
7984
}
8085

81-
export function cloneDeep<T>(obj: Readonly<T>): T
82-
{
83-
if (obj === null || typeof obj !== "object")
84-
{
85-
return obj;
86-
}
87-
88-
if (Array.isArray(obj)) {
89-
return obj.map((item) => cloneDeep(item)) as unknown as T;
86+
function cloneDeep(value: unknown): unknown {
87+
if (isArray(value)) {
88+
return value.map(item => cloneDeep(item));
89+
} else if (isDict(value)) {
90+
const cloned: Record<string, unknown> = {};
91+
Object.keys(value).forEach(key => {
92+
cloned[key] = cloneDeep((value as Record<string, unknown>)[key]);
93+
});
94+
return cloned;
95+
} else {
96+
return value;
9097
}
91-
92-
const clonedObj: Record<string, any> = {};
93-
94-
Object.keys(obj).forEach((key) => {
95-
clonedObj[key] = cloneDeep((obj as Record<string, any>)[key]);
96-
});
97-
98-
return clonedObj as T;
9998
}
10099

101-
export function mergeDeep(target: Readonly<any>, source: any): any {
102-
const output = cloneDeep(target);
103-
100+
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
101+
export function mergeDeep(target: Readonly<unknown>, source: Readonly<unknown>): any {
104102
if (!isObject(target))
105103
{
106104
return cloneDeep(source)
107105
}
108106

109-
if (isObject(target) && isObject(source)) {
107+
const output = cloneDeep(target);
108+
109+
if (isObject(output) && isObject(source)) {
110+
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
110111
Object.keys(source).forEach((key: any) => {
111112
if (isDict(source[key])) {
112113
if (key in target) {
113-
output[key] = mergeDeep(target[key], source[key]);
114+
output[key] = mergeDeep(target[key] as Readonly<unknown>, source[key]);
114115
} else {
115116
Object.assign(output, {[key]: source[key]});
116117
}
@@ -135,31 +136,51 @@ export function mergeDeep(target: Readonly<any>, source: any): any {
135136
* @param key Dot-separated key path specifying the value to retrieve.
136137
* @returns The value at the specified key path, or `undefined` if not found.
137138
*/
138-
export function getValue(target: any, key: string): any
139+
export function getValue(target: unknown, key: string): unknown
139140
{
140141
const keys = key.split(".");
141142

142143
key = "";
143144
do
144145
{
145146
key += keys.shift();
146-
if (
147-
isDefinedAndNotNull(target) &&
148-
(isDefinedAndNotNull(target[key]) || target[key] === null) &&
149-
(isDict(target[key]) || isArray(target[key]) || !keys.length)
150-
)
147+
const isLastKey = !keys.length;
148+
149+
if(isDefinedAndNotNull(target))
151150
{
152-
target = target[key];
153-
key = "";
151+
if (
152+
isDict(target) &&
153+
isDefined(target[key]) &&
154+
(isDict(target[key]) || isArray(target[key]) || isLastKey)
155+
)
156+
{
157+
target = target[key];
158+
key = "";
159+
continue;
160+
}
161+
162+
if(isArray(target))
163+
{
164+
const index = parseInt(key, 10);
165+
if (
166+
isDefined(target[index]) &&
167+
(isDict(target[index]) || isArray(target[index]) || isLastKey)
168+
)
169+
{
170+
target = target[index];
171+
key = "";
172+
continue;
173+
}
174+
}
154175
}
155-
else if (!keys.length)
176+
177+
if (isLastKey)
156178
{
157179
target = undefined;
180+
continue;
158181
}
159-
else
160-
{
161-
key += ".";
162-
}
182+
key += ".";
183+
163184
} while (keys.length);
164185

165186
return target;
@@ -174,22 +195,17 @@ export function getValue(target: any, key: string): any
174195
* @param value to set
175196
* @deprecated use insertValue() instead
176197
*/
177-
export function setValue(target: any, key: string, value: any): void {
178-
const keys = key.split('.');
179-
let current = target;
198+
export function setValue(target: Record<string, unknown>, key: string, value: unknown): void {
199+
const keys:string[] = key.split('.');
200+
let current:Record<string, unknown> = target;
180201

181202
for (let i = 0; i < keys.length; i++) {
182203
const key = keys[i];
183204

184-
// If we're at the last key, set the value
185205
if (i === keys.length - 1) {
186206
current[key] = value;
187207
} else {
188-
// If the key doesn't exist or isn't an object, create an empty object
189-
if (!current[key] || !isDict(current[key])) {
190-
current[key] = {};
191-
}
192-
current = current[key];
208+
current = (current[key] && isDict(current[key])) ? current[key] : {};
193209
}
194210
}
195211
}
@@ -204,12 +220,15 @@ export function setValue(target: any, key: string, value: any): void {
204220
* @param key E.g. "a.b.c"
205221
* @param value to set
206222
*/
207-
export function insertValue(target: Readonly<any>, key: string, value: any): any {
208-
return mergeDeep(target, createNestedObject(key, value));
223+
export function insertValue<T>(target: Readonly<T>, key: string, value: unknown): T {
224+
return mergeDeep(target, createNestedObject(key, value) as Readonly<unknown>);
209225
}
210226

211227

212228

213-
function createNestedObject(dotSeparatedKey: string, value: any): Record<string, any> {
214-
return dotSeparatedKey.split('.').reduceRight((acc, key) => ({ [key]: acc }), value);
229+
function createNestedObject(dotSeparatedKey: string, value: unknown): Record<string, unknown>|unknown
230+
{
231+
return dotSeparatedKey
232+
.split('.')
233+
.reduceRight<unknown>((acc, key) => ({ [key]: acc }), value);
215234
}

projects/ngx-translate/src/lib/utils.spec.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -238,8 +238,6 @@ describe("Utils", () =>
238238
expect(getValue(['A', ['a', 'b', 'c'], 'C'], '1.2')).toEqual("c");
239239

240240
expect(getValue("test", 'key')).not.toBeDefined();
241-
242-
expect(getValue("test", '1')).toEqual("e"); /// useless: substring
243241
})
244242

245243
});

0 commit comments

Comments
 (0)