Typescript: Add a property on an inner object with module augmentation

Viewed 444

Considering an external (npm) module extmod exposing the following interface in its declarations file:

interface Options {
  somevar?: string;
  suboptions?: {
    somesubvar?: string;
  };
}

How can I add a property somesubvar2 inside suboptions with module augmentation?

I've tried the following in an extmod.d.ts file:

declare module 'extmod' {
  interface Options {
    suboptions?: {
      somesubvar2?: string;
    };
  }
}

But it throws the following errors:

error TS2687: All declarations of 'suboptions' must have identical modifiers.
error TS2717: Subsequent property declarations must have the same type.  Property 'suboptions' must be of type '<SNIP>', but here has type '{ somesubvar2: string; }'.
2 Answers

This could have been done probably better, made available globally using ambient declarations, but it still makes the job done.

import Web3 from 'web3'
import type { Contract as TheBadContract } from 'xyz'

interface ContractMethods {
  // some properties...
}

interface Contract extends Modify<TheBadContract, {
  methods: ContractMethods // <- this `methods` is the actual overwritten property
}> {}

const contract: Contract = new web3.eth.Contract()

This was easy as the methods object was an immediate member and it is undefined on the original Contract type.

If you need to actually modify some deeply nested key, check out my ModifyDeep type below.

Modify: https://stackoverflow.com/a/55032655/985454
ModifyDeep: https://stackoverflow.com/a/65561287/985454

How can I add a property somesubvar2 inside suboptions with module augmentation?

In your example you changed the type suboptions from <SNIP> to { somesubvar2: string; }

You could patch <SNIP> type with additional property.

Related