1

I have a nested json like so, which I cannot modify as it is part of some package

const myjson = {
    properties: {
        'firstname':'david'
    },
    class: 'primary'
}

I want to add another key value to properties, so that it looks like

const myjson = {
    properties: {
        'firstname':'david',
        'lastname' :'watson'
    },
    class: 'primary'
}

So I used the following

myjson.properties['lastname'] = 'watson';

This gives the error

Element implicitly has an 'any' type because expression of type '"lastname"' can't be used to index type '{ firstname: string; }'.
  Property 'lastname' does not exist on type '{ firstname: string; }'.(7053)

I think I have to use as keyof typeof something like below which is wrong syntax and doesn't fix the error

myjson.properties['lastname' as typeof keyof myjson.properties] = 'watson';

Runnable code with the error can be seen here https://www.typescriptlang.org/play?#code/MYewdgzgLgBAtgTwFYXDAvDA3gKBvmABwCcRCBTYqAS3IgC5s8CWByAM2uOjAEM5yreqwAmvAG7URrZvgC+AGlkxgAG14QGMViWpxexBDLk5EKcADoSZSjToBtVup79BMDTCgIKIdjADW5Ai+8MioYFakFFS0EAC6GNoA7rxQ4awA3DigkCCq5BaqIADmABRm4QCUGUA

Edit#1: I made a small error in the order of typeof keyof in the above statement. Now the error is gone. The correct statement is

myjson.properties['lastname' as keyof typeof myjson.properties] = 'watson';

Corrected code is here https://www.typescriptlang.org/play?ssl=7&ssc=76&pln=7&pc=1#code/MYewdgzgLgBAtgTwFYXDAvDA3gKBvmABwCcRCBTYqAS3IgC5s8CWByAM2uOjAEM5yreqwAmvAG7URrZvgC+AGlkxgAG14QGMViWpxexBDLk5EKcADoSZSjToBtVup79BMDTADW5BCHYwoBAo-eGRUMCtSCipaCABdDG0Ad14ocNYAbhxQSBBVcgtVEABzAAozcIBKDKA

Edit#2: Found one more way to do this without the error

Object.assign(myjson.properties, {'lastname': 'watson'});
2
  • What keys can exist on properties? Any string or only firstname and lastname? Commented May 17, 2023 at 17:45
  • @Lesiak There are more keys that I need to add like state , country. Or did you mean the keys could be of another data type? Commented May 17, 2023 at 17:51

1 Answer 1

2

The inferred type of myjson is

{
  properties: {
    firstname: string;
  };
  class: string;
}

You cannot add new properties to this type - you need to let TS compiler know that properties can accept additional keys. You need to add an explicit type to myjson

Option 1: Index signature

Use Index signature if you have:

  • arbitrary property names
  • all sharing same type
interface MyData {
  properties: {
    [key: string]: string
  },
  class: string
}

const myjson: MyData = {
    properties: {
        'firstname':'david'
    },
    class: 'primary'
}

myjson.properties.lastname = 'watson';

Option 2: optional properties

Use optional properties if you have:

  • a few well-defined property names
  • possibly with different types
interface MyData {
  properties: {
    firstname?: string,
    lastname?: string,
    age?: number
  },
  class: string
}

const myjson: MyData = {
    properties: {
        'firstname':'david'
    },
    class: 'primary'
}

myjson.properties.lastname = 'watson';

Option 3: create new object

const myjson: MyData = {
    properties: {
        'firstname':'david'
    },
    class: 'primary'
}

const newJson = {
    ...myjson,
    properties: {
        ...myjson.properties,
        lastname: 'watson'
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

I made a small error in the statement to add an additional property and now the error is gone. There is no need to modify myjson. I have added the details in the edit.
@ontherocks your solution ('lastname' as keyof typeof myjson.properties) allows you to add the property to the object, but the compiler still believes that the type is not changed (thus myjson.properties.lastname is flagged as an error). If possible, I would try to avoid this kind of difference between compile-time interface and actual runtime type - added option 3 as another alternative.
myjson.properties.lastname will be flagged as an error because of the precise reason that you've mentioned (i.e. the compiler still believes that the type is not changed). Hence, we have to use as keyof typeof everywhere where we want to use myjson.properties.lastname, for e.g. console.log(myjson.properties['lastname' as keyof typeof myjson.properties]);
IMHO myjson.properties['lastname' as keyof typeof myjson.properties] is far from ideal

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.