Skip to content

Inconsistent compatibility of generic interfaces #20738

Closed
@c7hm4r

Description

@c7hm4r

TypeScript Version: 2.7.0-dev.20171216

Code

class Base {}
class Derived extends Base {
  public derived = true;
}

interface ISetter0<T> {
  set(x: T): void;
}
interface ISetter1<T> {
  set: (x: T) => void;
}

const derivedSetter0: ISetter0<Derived> = { set: () => null }; // assignment 0
const derivedSetter1: ISetter1<Derived> = { set: () => null }; // assignment 1

let baseSetter0: ISetter0<Base> = derivedSetter0; // assignment 2
let baseSetter1: ISetter1<Base> = derivedSetter1; // assignment 3

baseSetter0 = derivedSetter1; // assignment 4
baseSetter1 = derivedSetter0; // assignment 5

Compiler options:

  "compilerOptions": {
    "strict": true,
    "strictFunctionTypes": true,
  },

Expected behavior:

Compilation should fail at assignments 2, 3, 4 and 5.

Actual behavior:

Compilation only fails at assigments 3 and 5.

tsc output:

test.ts(17,5): error TS2322: Type 'ISetter1<Derived>' is not assignable to type 'ISetter1<Base>'.
  Type 'Base' is not assignable to type 'Derived'.
    Property 'derived' is missing in type 'Base'.
test.ts(20,1): error TS2322: Type 'ISetter0<Derived>' is not assignable to type 'ISetter1<Base>'.
  Types of property 'set' are incompatible.
    Type '(x: Derived) => void' is not assignable to type '(x: Base) => void'.
      Types of parameters 'x' and 'x' are incompatible.
        Type 'Base' is not assignable to type 'Derived'.

Additional Notes:

The expected behavior handles contravariance correctly, the actual behavior not.

This bug could be part of the more general issue “Covariance / Contravariance Annotations”, but a full covariance / contravariance implementation is probably not necessary to fix this bug. It would probably also be fixed if
“Proposal: covariance and contravariance generic type arguments annotations” is implemented.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Working as IntendedThe behavior described is the intended behavior; this is not a bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions