Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

strictNullChecks causes error: hasOwnProperty does not exist for generic types

Tags:

typescript

My code works well without --strictNullChecks.

When enabling --strictNullChecks, the following error occurs:

Property 'hasOwnProperty' does not exist on type 'T1'.
Property 'hasOwnProperty' does not exist on type 'T2'.

function extend<T1, T2>(arg1: T1, arg2: T2): T1 & T2 {
    const result: Partial<T1 & T2> = {};
    for (const prop in arg1) {
        if (arg1.hasOwnProperty(prop)) { // error when using --strictNullChecks
            (result as T1)[prop] = arg1[prop];
        }
    }
    for (const prop in arg2) {
        if (arg2.hasOwnProperty(prop)) { // error when using --strictNullChecks
            (result as T2)[prop] = arg2[prop];
        }
    }
    return result as T1 & T2;
}

like image 838
Harry Avatar asked Aug 03 '19 08:08

Harry


2 Answers

Since they're unbounded generics, T1 or T2 could be null or undefined, neither of which has hasOwnProperty.

You'll need to mark them as extending object:

function extend<T1 extends object, T2 extends object>(arg1: T1, arg2: T2): T1 & T2 {
// ---------------^^^^^^^^^^^^^^^-----^^^^^^^^^^^^^^
    const result: Partial<T1 & T2> = {};
    for (const prop in arg1) {
        if (arg1.hasOwnProperty(prop)) { // error when using --strictNullChecks
            (result as T1)[prop] = arg1[prop];
        }
    }
    for (const prop in arg2) {
        if (arg2.hasOwnProperty(prop)) { // error when using --strictNullChecks
            (result as T2)[prop] = arg2[prop];
        }
    }
    return result as T1 & T2;
}
like image 113
T.J. Crowder Avatar answered Sep 28 '22 08:09

T.J. Crowder


You can find more on the subject here, but basically Typescript doesn't know that your generic type is an Object.

It is assuming, and rightfully so, that it could be anything, including a string, number or even null. So it wouldn't make any sense to allow you to call hasOwnProperty on those.

You need to specify your generic types a bit more than that.

function extend<T1 extends object, T2 extends object>(arg1: T1, arg2: T2): T1 & T2;
like image 43
Morphyish Avatar answered Sep 28 '22 07:09

Morphyish