Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(TS): extending canvas and object event types #8926

Merged
merged 4 commits into from
May 18, 2023

Conversation

jiayihu
Copy link
Contributor

@jiayihu jiayihu commented May 17, 2023

Motivation

I'll progressively update the PR to make fabric (beta5 currently) more type-friendly for the consumer.

Changes

  • Make the canvas and object events extendible by using interfaces instead of type as interfaces allow "Interface merging" and module augmentation: https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation
  • I've re-exported the types from EventTypeDefs so that they can be used along with module augmentation. It looks like that if you do module augmentation, e.g. declare module "fabric" as shown below, you can't anymore import any type from a submodule (e.g. import { ModifiedEvent } from "fabric/dist/src/EventTypeDefs").
    This is very inconvenient when you need to type the event handler for instance: onModified(event: ModifiedEvent) {}.
    So far I haven't found any solution for this other than re-exporting the types so that they are directly available using import { ModifiedEvent } from "fabric/"

In Action

I can now do the following module augmentation so that object.fire("custom:transform:begin") doesn't raise an error:

// fabric-events.d.ts
import "fabric"

declare module "fabric" {
  interface ObjectEvents {
    "custom:transform:begin": void;
    "custom:transform:end": void;
  }
}

@ShaMan123
Copy link
Contributor

My intention for the consumer was to do something like

type MyObjectsEvents = ObjectEvents & {
   "custom:transform:begin": void;
    "custom:transform:end": void;

}


class MyObject extends FabricObject<Props, SerailizedProps, MyObjectsEvents> {


}

However, this change is welcome IMO.
A single way to do something is not good enough and is too restricting.

@jiayihu
Copy link
Contributor Author

jiayihu commented May 17, 2023

I had the same idea and I was actually refactoring our code so that every object class extends from MyObject. Then I remembered that we do class StickyNote extends fabric.Textbox. In that case it doesn't extend from MyObject.

We could change Textbox<EventSpec = ITextEvents> extends IText<EventSpec = ITextEvents> but in our case we need to use declaration merging anyway for all the other type definitions (properties, methods) that get added to fabric.Object.

Also the class StickyNote extends fabric.Textbox issue made me suspicious immediately, as ideally I would like "StickyNote to extend from fabric.Textbox, which in turn I would like to extend from MyObject instead of fabric.Object". All this inheritance got me scared immediately as I didn't want to get trapped in a classical OOP hell. So I kept everything as it is and went to the declaration merging approach, which was quick and easy as soon as I did the changes in this PR.

@asturur
Copy link
Member

asturur commented May 17, 2023

Yes the merge feature of interfaces ( that as far as i understand are the only thing that differentiate them by types ) makes subclassing easier for some things.

Copy link
Contributor

@ShaMan123 ShaMan123 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@ShaMan123 ShaMan123 changed the title Allow extending canvas and object events fix(TS): extending canvas and object event types May 18, 2023
@ShaMan123 ShaMan123 merged commit f2090db into fabricjs:master May 18, 2023
@jiayihu jiayihu deleted the chore/beta6-types branch May 18, 2023 13:47
@asturur asturur mentioned this pull request May 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants