-2

I am working with a code that returns JSON | null type, hoping to change the value of a specific properties if those properties are

   some function...
   return {
        property_one: some_obj.property_one
    }

Objective is to change only a certain fields in this property_one that looks like

{
    name: 'Some Name',
    address: 'Some Address'
}

to { name: 'Some Name', address: 'this is private' }

but if I pass this property to a helper function to access nested object it complains.

Honestly, this is what I expected,

some_obj.property_one.address = '*this is private*';

but this raises an Error below.

> Property 'key' does not exist on type 'object'.

I even tried turning them into {[key:string]:unknown}, and surprisingly this works for one more level, but not further down.

const jsonlike:{[key:string]:unknown} = {"a":"first", "b":"Second", "c":"Third", "d": {"e":"Fifth"}}

console.log(typeof(jsonlike))

console.log(jsonlike.d) // works till here
console.log(jsonlike.d.e) // doesn't work, jsonlike.d' is of type 'unknown'.

Can anyone please guide me through what I'm not understanding in TypeScript?

3
  • Just use a const assertion? Commented May 31 at 6:11
  • This is honestly quite difficult to read, not only because every example uses different keys (property_one, address, key, d, e...) Just going by the last example, can't you just type it as {[key:string]: any} ? Commented May 31 at 6:29
  • @GuyIncognito Thanks for the feedback on the quality of the question. I appreciate it. It's just that typing :any is just not why we use TypeScript, and I just want to figure out how this actually work so that I don't cut corners.
    – dessigma
    Commented Jun 2 at 23:16

1 Answer 1

1

Define a type that represents the structure of the nested object.

interface PropertyOne {
    name: string;
    address: string;
}

interface SomeObj {
    property_one: PropertyOne | null;
}

Use type assertion or type guard to safety access and modify the nested property

function modifyAddress(someObj: SomeObj) {
    if (someObj.property_one) { // Check if property_one is not null
        // Safely modify the address
        someObj.property_one.address = 'this is private';
    }
}

// Example usage:
const some_obj: SomeObj = {
    property_one: {
        name: 'Some Name',
        address: 'Some Address'
    }
};

modifyAddress(some_obj);
console.log(some_obj);

If you still want to work with {[key: string]: unknown}, you'll need to use type assertions:

interface NestedObj {
    e: string;
}

const jsonlike: {[key: string]: unknown} = {"a": "first", "b": "Second", "c": "Third", "d": {"e": "Fifth"}};

if (typeof jsonlike.d === 'object' && jsonlike.d !== null && 'e' in jsonlike.d) {
    const d = jsonlike.d as NestedObj;
    console.log(d.e); // Now you can access d.e
}
1
  • Oh wow, that is amazing. I see, I need to specify the type for nested objects as well in order to access it. It's interesting how this seemed to work easily when I worked on React, but not on ts node. I was probably missing some core knowledge regarding how I treat some JSON data. Again, thank you for this answer, I truely appreciate it!
    – dessigma
    Commented Jun 2 at 23:23

Not the answer you're looking for? Browse other questions tagged or ask your own question.