angulartypescripteslintlintjslint

esLint gives error The body of a for-in should be wrapped in an if statement to filter unwanted properties from the prototype


I am using esLint for my angular project it throw an error for below code

private calculateFieldValue(value: any): any {
                let isEmptyObject = false;
                if (value && Array.isArray(value) && value.length === 1 && value[0]) {
                    for (const subAttr in value[0]) {
                        if (value[0].hasOwnProperty(subAttr)) {
                            if (value[0][subAttr]) {
                                break;
                            }
                        }
                        isEmptyObject = true;
                    }
                }
                return isEmptyObject ? null : value;
            }

It threw the error:

error The body of a for-in should be wrapped in an if statement to filter unwanted properties from the prototype guard-for-in


Solution

  • Although you do have a hasOwnProperty check, it doesn't enclose the whole of the loop body; isEmptyObject = true; will run even if the value[0] doesn't have that property. The linter wants you to only run statements in the body if the hasOwnProperty succeeds.

    for (const subAttr in value[0]) {
        if (value[0].hasOwnProperty(subAttr)) {
            if (value[0][subAttr]) {
                break;
            }
            isEmptyObject = true;
        }
    }
    

    I'd also highly discourage using any - that defeats the purpose of TypeScript by effectively disabling many types of type-checking. You're returning either the array or null, so use generics to indicate the type of the array instead of using any.

    A nicer way to do this would be to use Object.values to see if any values are truthy - after all, you don't care about the keys at all, only the values.

    function getSubarrayObjectWithTruthyProperty<T extends unknown>(value: Array<T> | unknown) {
        if (value && Array.isArray(value) && value.length === 1) {
            const item: unknown = value[0];
            if (item && typeof item === 'object' && Object.values(item).some(Boolean)) {
                return value as T;
            }
        }
        return null;
    }