Skip to content

[3.5.0-dev.20190516] Incorrect type error for mixin #31426

Open

Description

When using the mixin pattern, there are 2 main notations to define the type of the mixin entity.
The mixin pattern:

export type AnyFunction<A = any>        = (...input : any[]) => A
export type AnyConstructor<A = object>  = new (...input : any[]) => A
export type Mixin<T extends AnyFunction> = InstanceType<ReturnType<T>>

export const Box = <T extends AnyConstructor<object>>(base : T) =>
class Box extends base {
    value       : any
}

1st notation:

export type Box = Mixin<typeof Box> {}

2nd notation:

export interface Box extends Mixin<typeof Box> {}

The 1st notation can not be used for recursive definitions (#29872). Because of that we primarily use 2nd notation. It works fine in most cases, however I found a case, when it produces invalid type error. The full snippet to reproduce the problem below.

Note:

  • The typechecker correctly figures out that there's no zxc property on this, inside the observe method of Quark mixin.
  • In that method, it does not complain about the this.value usage
  • It does complain, when value is used on function argument
  • If you'll switch the Quark mixin to the 1st notation, the error will disappear

Expected behavior:

  • No type errors for the definition of test function below
export type AnyFunction<A = any>        = (...input : any[]) => A
export type AnyConstructor<A = object>  = new (...input : any[]) => A
export type Mixin<T extends AnyFunction> = InstanceType<ReturnType<T>>

export const Box = <T extends AnyConstructor<object>>(base : T) =>
class Box extends base {
    value       : any
}
export interface Box extends Mixin<typeof Box> {}

export const Observable = <T extends AnyConstructor<object>>(base : T) =>
class Observable extends base {
    observe () : Quark {
        return
    }
}
export interface Observable extends Mixin<typeof Observable> {}

export const Quark = <T extends AnyConstructor<Box & Observable>>(base : T) =>
class Quark extends base {

    observe () : Quark {
        // No error here!
        this.value
        
        // error: Error:(28, 14) TS2339: Property 'zxc' does not exist on type 'Quark'.
        this.zxc
        
        return
    }
}
export interface Quark extends Mixin<typeof Quark> {}

const test = (a : Quark) => a.value // <-- Error:(35, 28) TS2339: Property 'value' does not exist on type 'Quark'.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    BugA bug in TypeScriptFix AvailableA PR has been opened for this issue

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions