Search code examples
typescriptmongoosemongoose-models

Typescript interface are not overloading / merging subsequent interface fields


I know that interfaces in typescript allow us to merge different types. When i tried to do so, i am getting error while transpiling the script.

Here is my buggy interface

export interface StoreConfig extends Document, TimeStamps {
  type: 'webhook'
  metadata: {
    endpoint: string
    method: HttpMethod
    secret: string
    event: string | string[]
  }
}

export interface StoreConfig extends Document, TimeStamps {
  type: 'buylink'
  metadata: {
    prodId: string
    key: string
    expire: Date
  }
}

export interface StoreConfig extends Document, TimeStamps {
  type: 'paymentmethod'
  metadata: {
    apiKey: string
    mode: string
    whsecret: string
  }
}

I am getting this error on transpiling ts script

Subsequent property declarations must have the same type.  Property 'type' must be of type '"webhook"', but here has type '"buylink"'.

PS: I have seen many libraries (for example: nodemailer, inquirer) are loading typings based on some flag or condition.


Solution

  • /**
     * Simplified example
     */
    
    export interface StoreConfig extends Document {
        type: 'webhook'
    
    }
    
    export interface StoreConfig extends Document {
        type: 'buylink'
    
    }
    
    export interface StoreConfig extends Document {
        type: 'paymentmethod'
    }
    
    /**
     * This is how it works
     * 1) 
     */
    
    export interface A {
        type: 'buylink'
    
    }
    
    export interface A {
        payload: number
    }
    
    type O = keyof A // type | payload
    
    /**
     * Because you can't do smth like that
     */
    
    type CustomType = 'buylink' & 'webhook' // never
    
    /**
     * Above type is never because it is irrepresentable
     * Please treat merging as & operator on high level
     */
    

    Demo1

    What you need to do is to make a union type. Just like @ritaj wrote in his comment:

    export interface StoreConfig1 extends Document {
        type: 'webhook'
    
    }
    
    export interface StoreConfig2 extends Document {
        type: 'buylink'
    
    }
    
    export interface StoreConfig3 extends Document {
        type: 'paymentmethod'
    }
    
    type StoreConfig = StoreConfig1 | StoreConfig2 | StoreConfig3
    

    Demo2