I´m trying to clean a typed object from empty optional properties with a helper function, and it all works fine. The problem is that i'm running in strict mode and cant figure out how to solve the strict error i get on the result in the if-statement.
export function removeEmptyOptionalProperties<T>(obj: T extends unknown ? any : any): T {
const result = {} as T;
Object.keys((obj)).forEach(prop => {
if (obj[prop] || obj[prop] === false || obj[prop] === 0 || obj[prop] === Array.isArray) {
/* Here ---> */ result[prop] = obj[prop] as T;
}
});
return { ...result };
}
Test example:
const testObject = {
undefinedProp: undefined,
nullProp: null,
falseProp: false,
zeroProp: 0,
emptyString: '',
filledString: 'filledString',
filledObject: {
filledString: 'filledString',
},
filledArray: [
{
filledString: 'filledString',
},
],
};
const result = removeEmptyOptionalProperties(testObject);
console.log('result:', result);
The const result shouldn't have any properties that is: undefined, null or ''. Ive tried to look at the error it generates, but cant figure it out how to solve it. Error: 'Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'unknown'. No index signature with a parameter of type 'string' was found on type 'unknown'.ts(7053) ' https://typescript.tv/errors/#TS7053
As said, this function works, but 'strict' dosen´t like it. So I need a solution so 'strict' likes it. Any ideas?
CodePudding user response:
There are 2 issues in the above code:
Object.keys(obj).forEach
doesn't take into account, the type of the keys. All the keys will be of typestring
. So, you will have to manually cast them to the typekeyof T
.- In this code,
result[prop] = obj[prop] as T
, you are convertingobj[prop]
to typeT
and assigning toresult[prop]
which is incorrect becauseresult
is of typeT
andresult[prop]
is of typeT[typeof prop]
.
export function removeEmptyOptionalProperties<T>(obj: T extends unknown ? any : any): T {
const result = {} as T;
Object.keys((obj)).forEach((prop) => {
const key = prop as keyof T // Address first problem
if (obj[prop] || obj[prop] === false || obj[prop] === 0 || obj[prop] === Array.isArray) {
result[key] = obj[prop] as T[typeof key]; // Address second problem
}
});
return { ...result };
}
CodePudding user response:
I think I solved it by making the result as a Record, which means that you can add any properties to that object, then returning it as the type that came in.
Like this:
function removeEmptyOptionalProperties<T>(obj: T extends unknown ? any : any): T {
/* const result = {} as T; */
const forLoopResult: Record<string, unknown> = {};
Object.keys((obj)).forEach(prop => {
if (obj[prop] || obj[prop] === false || obj[prop] === 0 || obj[prop] === Array.isArray) {
forLoopResult[prop] = obj[prop];
}
});
const result: unknown = { ...forLoopResult };
return result as T;
}