Skip to content

Unable to expectError on decorator applicability #206

@tbroyer

Description

@tbroyer

I'm writing a helper library around decorators (standard ECMAScript ones, as supported by TypeScript 5+ and @babel/plugin-proposal-decorators) and have been unable to test errors when applying them.

Here's a self-contained reproduction:

import { expectError } from "tsd";

class Base extends HTMLElement {
  foo() {}
}

const classDec = <T extends new (...args: any[]) => Base>(
  value: T,
  context: ClassDecoratorContext<T>
) => {
  return class DecoratedClass extends value {};
};

(
  @classDec
  class extends Base {}
);
expectError(
  @classDec
  class {}
);
expectError(
  @classDec
  class extends Document {}
);
expectError(
  @classDec
  class extends HTMLElement {}
);
expectError(() => {
  @classDec
  abstract class Test extends Base {}
});

classDec can only be applied to a concrete class extending Base, so the anonymous class extending nothing, Document, HTMLElement, or an abstract class are errors.

This however fails with:

  repro.test-d.ts:19:3
  ✖  19:3  Unable to resolve signature of class decorator when called as an expression.
  Argument of type typeof (Anonymous class) is not assignable to parameter of type new (...args: any[]) => Base.
    Type (Anonymous class) is missing the following properties from type Base: foo, accessKey, accessKeyLabel, autocapitalize, and 291 more.                                                                                                                                                                                                                                                                                                            
  ✖  23:3  Unable to resolve signature of class decorator when called as an expression.
  Argument of type typeof (Anonymous class) is not assignable to parameter of type new (...args: any[]) => Base.
    Type Document is missing the following properties from type Base: foo, accessKey, accessKeyLabel, autocapitalize, and 132 more.                                                                                                                                                                                                                                                                                                                     
  ✖  23:3  Decorator function return type { new (...args: any[]): classDec<new (...args: any[]) => Base>.DecoratedClass; prototype: classDec<any>.DecoratedClass; } & (new (...args: any[]) => Base) is not assignable to type void | typeof (Anonymous class).                                                                                                                                                                                                                                                                                                                                                                                                
  ✖  23:3  Decorator function return type { new (...args: any[]): classDec<new (...args: any[]) => Base>.DecoratedClass; prototype: classDec<any>.DecoratedClass; } & (new (...args: any[]) => Base) is not assignable to type void | typeof (Anonymous class).
  Type { new (...args: any[]): classDec<new (...args: any[]) => Base>.DecoratedClass; prototype: classDec<any>.DecoratedClass; } & (new (...args: any[]) => Base) is not assignable to type typeof (Anonymous class).
    Type classDec<new (...args: any[]) => Base>.DecoratedClass & Base is missing the following properties from type Document: URL, alinkColor, all, anchors, and 92 more.  
  ✖  27:3  Unable to resolve signature of class decorator when called as an expression.
  Argument of type typeof (Anonymous class) is not assignable to parameter of type new (...args: any[]) => Base.
    Property foo is missing in type HTMLElement but required in type Base.                                                                                                                                                                                                                                                                                                                                                                              
  ✖  31:3  Unable to resolve signature of class decorator when called as an expression.
  Argument of type typeof Test is not assignable to parameter of type new (...args: any[]) => Base.
    Cannot assign an abstract constructor type to a non-abstract constructor type.                                                                                                                                                                                                                                                                                                                                                                                   

  6 errors

Same result as if I omitted the expectError from the file.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions