3

I have an interface (in the example is called "Example") that includes a function type ("exampleFunction"), but this function takes a super class as an input parameter, and typescript reports an error stating that i can't use subtypes as input because they have some properties that are not present in the super type.

Here is an example:

interface SuperType {
   propertyA: string
}

interface SubTypeA extends SuperType {
   subPropertyA: number
}

interface SubTypeB extends SuperType {
   subPropertyB: number
}

interface Example {
   exampleFunction: (input: SuperType) => void
}

i have a problem if i write:

const example: Example = {
   exampleFunction: (input: SubTypeA) => {console.log("nothing")}
}
kelsny
  • 23,009
  • 3
  • 19
  • 48
Bambatrack
  • 51
  • 4
  • Related: https://stackoverflow.com/questions/72092484/typescript-this-in-interface-should-reference-itself-and-children-not-only-itse – kelsny May 03 '22 at 16:58

1 Answers1

0

The problem is easier to spot if you make your function use the SubTypeA only property.

const example: Example = {
   exampleFunction: (input: SubTypeA) => {console.log(input.subPropertyA.toFixed())}
}

The function itself is perfectly valid (it accepts a SubTypeA argument and accesses one of the properties. However, the Example type can only guarantee that a SuperType is passed in. So the other unique properties of SubTypeA can't be guaranteed to exist.

For example:

const superType: SuperType = { propertyA: 'foo' }
example.exampleFunction(superType)
// valid call, but crashes because `subPropertyA` doesn't exist

Perhaps one fix is to make your function handle a SuperType or a SubTypeA?

const example: Example = {
   exampleFunction: (input: SuperType | SubTypeA) => {
       if ('subPropertyA' in input) {
            console.log(input.subPropertyA.toFixed())   
       }
    }
}

const superType: SuperType = { propertyA: 'foo' }
example.exampleFunction(superType) // works

const subTypeA: SubTypeA = { propertyA: 'foo', subPropertyA: 123 }
example.exampleFunction(subTypeA) // works

Playground

Alex Wayne
  • 178,991
  • 47
  • 309
  • 337
  • What's more interesting is that if you define the function type in `Example` with method syntax and not arrow syntax it works! In the question I linked it explains why. Peculiar isn't it? – kelsny May 03 '22 at 17:08
  • Now that _is_ strange. https://tsplay.dev/WPZDLN I have no idea why that is. Smells like a bug. – Alex Wayne May 03 '22 at 17:13
  • "During development of this feature, we discovered a large number of inherently unsafe class hierarchies, including some in the DOM. Because of this, the setting only applies to functions written in function syntax, not to those in method syntax" – kelsny May 03 '22 at 17:16
  • Yeah, the whole point of this is because i wanted to exploit polymorphism and make the method available to all the interfaces that extend SuperType. It seems that using method syntax it doesnt complain anymore. – Bambatrack May 03 '22 at 17:48