0

I am new to typescript

I have an interface ABC in which I want either propA or propB to be there. it also have other properties

interface ABC {
  propA: string 
  propB: string 
  propC: string
  propD?: string 
}

How can I do that?

I did this based on this answer https://stackoverflow.com/a/40510700/10433835

interface ABC { 
   propC: string
   propD?: string 
}

interface A extends ABC {
  propA: string
}

interface B extends ABC {
    propB: string
}  

export type final = A | B

but then when I do something like this

 function somethingCalled (a:A) {
 }

 const b:final = req.body 

 somethingCalled(b)

it throws following error Argument of type 'final' is not assignable to parameter of type 'interface A'.

Alwaysblue
  • 9,948
  • 38
  • 121
  • 210
  • The compiler is correct. You told it "either `propA` or `propB` exists on my variable" and then you went and tried to call a function that demands a `propA` be there on that variable. What if `propB` is there instead? That function won't work right. – Silvio Mayolo Nov 10 '21 at 05:29
  • Silvio, Can you please also tell how to fix it? – Alwaysblue Nov 10 '21 at 05:30
  • Also notice that `interface A extends ABC` and `interface B extends ABC`... that's completely useless since ABC already has `propA` and `probB`. Did you mean to not extend it? – Samathingamajig Nov 10 '21 at 05:30
  • @Samathingamajig updated the question – Alwaysblue Nov 10 '21 at 05:33

1 Answers1

0

I think what you want is to use discriminating union where a union's individual object is differentiated by the property that discriminates them with each other. In your case, propA tells that it is A and propB tells, it is B. Here is how we use them:

interface ABC {
  propC: string
  propD?: string 
}

interface A extends ABC {
  propA: string
  anotherA: number;
}

interface B extends ABC {
    propB: string
    somethingB: boolean;
}  

export type FinalType = A | B

 function somethingCalled (a:FinalType) {
     if('propA' in a){
         a.anotherA
         a.somethingB; // Error: Property 'somethingB' does not exist on type 'A'
     } else {
         a.somethingB
         a.anotherA // Error: Property 'anotherA' does not exist on type 'B'.
     }
 }

const req: any = '';

 const b:FinalType  =( req as any).body 

 somethingCalled(b)

You can see how Typescript could tell other properties don't belong to the type once discrimination is made clear.

TS Playground link: https://tsplay.dev/mpvDpw

Nishant
  • 54,584
  • 13
  • 112
  • 127