Home > Net >  Typescript method with Child/Parent arguments are not assignable
Typescript method with Child/Parent arguments are not assignable

Time:08-22

Why this does not work in typescript?

class Parent {
    id: string = ''
}

class Child extends Parent{
    name: string = ''
}



const fails: (created: Parent) => void = (created: Child) => { return };
const failsToo: ({ created }: { created: Parent }) => void = ({ created }: { created: Child }) => { return };

At least for me the error is very weird:

Type '(created: Child) => void' is not assignable to type '(created: Parent) => void'.
  Types of parameters 'created' and 'created' are incompatible.
    Property 'name' is missing in type 'Parent' but required in type 'Child'

It seems like it is trying to assign a Parent to a Child, but the in the real code is backwards (Trying to assign a method parameter that is a Child to a Parent. Which it make sense because Child is a super set of Parent)

Am I missing something?

We can verify this here: https://www.typescriptlang.org/play?#code/MYGwhgzhAEAKYCcCmA7ALtA3gKGn6AlgCYBc0EaCBKA5tALzQDkT2AvttqJDAMIAWBEEWhIAHmlREY8ZOhz5oKMAFskZClVoNmrDpy4B7FBWgAzMEIhkAFMGRhJpOIlRoAlAwB80AG6HiHTsHJzIBISJPeh9MaGQ0AFcEFGg2AG4jEwwLKwAVQ0NbWPskRyQRNjJikPKyWTdUqJ9-QMYbatKnVKroErLncOFG7yw4pETk1LSgA

CodePudding user response:

Function types are contravariant in their parameter types. The types counter-vary. They vary in the opposite direction from each other. So if A extends B, then ((x: B)=>void) extends ((x: A)=>void), not ((x: A)=>void) extends ((x: B)=>void). This is a natural consequence of type theory, but you could convince yourself of this necessity by imagining trying to pass narrower/wider types to functions than they expect and seeing what happens. For example, imagine this succeeded:

const fails: (created: Parent) => void =
    (created: Child) => { created.name.toUpperCase() };

The function (created: Child) => { created.name.toUpperCase() } is fine by itself; it accepts a Child and accesses its name property, which is a string, so it has a toUpperCase() method. But you've assigned it to a variable of type (created: Parent) => void. And that means you can call fails() like this:

fails(new Parent()); // okay at compile time, but
//            
  • Related