Type Task.perform as a property - #615
Conversation
perform is bound at runtime (this.perform = this._perform.bind(this)),
but typed as a method, so typescript-eslint's unbound-method reports
{{on "click" this.task.perform}}.
As a property, its args are checked contravariantly: a Task<T, [string]>
no longer fits Task<unknown, unknown[]>. Task<any, any[]> still fits.
a898252 to
2f93a00
Compare
|
I don't know what "contravariantly" means, mainly I just want to know "is this likely to bite anyone" for the 99% use caes of ember-concurrency, then I'll merge. |
|
First: it only affects TypeScript compilation, never runtime, and only code that stores a task in a type that accepts any arguments, like I asked claude to find public TypeScript projects that use ember-concurrency (boxel, ember-power-select, hashicorp/design-system, ember-bootstrap, …), and of 13, 12 are unaffected. One, eclipse-pass/pass-ui, uses Task<unknown, unknown[]> as "any task" in 5 places. passing So 99% is maybe a stretch. It can break compilation, so maybe bump as a major? (integers are cheap, etc) |
|
I think safe to release as minor. In case major issues i'll revert and publish a new minor and then push major with the fix. |
performis bound in the constructor (this.perform = this._perform.bind(this)), but typed as a method. So typescript-eslint'sunbound-methodreports{{on "click" this.task.perform}}when type-aware rules run on templates (emberjs/rfcs#1045 comment).Breaking (types only): as a property,
perform's args are checked contravariantly, so aTask<void, [string]>no longer fitsTask<unknown, unknown[]>. That assignment was unsound: it allowedperform(123)on a task that takes a string. Code that means "any task" can useTask<any, any[]>, which still fits. The type tests pass.Non-breaking alternative, if you prefer: type the property through a method signature, as
@types/reactdoes for event handlers. The args stay bivariant, so assignability does not change, andunbound-methodstill sees a property:Cowritten by Claude