Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Property does not exist on type 'object'

Tags:

typescript

I am getting various different data structures from external sources. In get() i am checking for undefined and existence of the property, but still getting compiler errors.

Is there a quick fix for that as we are just prototyping at the moment ?

class MyCache {
  private map: Map<string, object>;

  constructor() {
    this.map = new Map<string, object>();
  }

  populateMap(uuid: string): boolean {
    // ... getting a JSON object from somewhere
    let externalData: object = {};
    if (uuid == 'abc...') {
      externalData = {"bar": "BAR", "session": uuid}
    } else if( uuid == "def...") {
      externalData = {"foo": "FOO", "session": uuid}
    // ... some more else ifs ...
    } else {
      externalData = {"baz": "BAZ", "session": uuid}
    }
    this.map.set(uuid, externalData);
    console.log(externalData);
    return true;
  }

  get(uuid: string) {
    let response = this.map.get(uuid) || {'session': null};
    if (response.hasOwnProperty('session')) {
      return response.session;
    }
    return '';
  }
}

Error:

Property 'session' does not exist on type 'object'.
like image 768
Maurice Meyer Avatar asked May 06 '26 23:05

Maurice Meyer


2 Answers

AFAIK, type object is too general. I think it is better to use Record<string, unknown>. Please see ts eslint rule:

Unsafe:

//bad
const lowerObj: object = {};

Safe:

// good
const lowerObj: Record<string, unknown> = {};

Using hasOwnProperty is ok, but using Object.prototype.hasOwnProperty.call(foo, "bar") is much better. See eslint rule.

Here you can find recent optimization of V8 engine regarding using hasOwnProperty.

You can find more typings for hasOwnProperty in my article

Hence, this code should be ok:

class MyCache {
    private map: Map<string, Record<string, unknown>>;

    constructor() {
        this.map = new Map<string, Record<string, unknown>>();
    }

    populateMap(uuid: string): boolean {
        // ... getting a JSON Record<string, unknown> from somewhere
        let externalData: Record<string, unknown> = {};
        if (uuid == 'abc...') {
            externalData = { "bar": "BAR", "session": uuid }
        } else if (uuid == "def...") {
            externalData = { "foo": "FOO", "session": uuid }
            // ... some more else ifs ...
        } else {
            externalData = { "baz": "BAZ", "session": uuid }
        }
        this.map.set(uuid, externalData);
        console.log(externalData);
        return true;
    }

    get(uuid: string) {
        let response = this.map.get(uuid) || { 'session': null };
        if (response.hasOwnProperty('session')) {
            return response.session;
        }
        return '';
    }
}

Playground

like image 133
captain-yossarian Avatar answered May 11 '26 04:05

captain-yossarian


  1. Use Object instead of object link
  2. Use 'key' in obj instead of hasOwnProperty link
class MyCache {
    private map: Map<string, Object>;

    constructor() {
        this.map = new Map(); // No need for generic parameters, type is already set in the property declaration
    }

    get(uuid: string) {
        let response = this.map.get(uuid) || { 'session': null };
        if ('session' in response) {
            return response.session;
        }
        return '';
    }
}
like image 22
Roberto Zvjerković Avatar answered May 11 '26 02:05

Roberto Zvjerković



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!