Git Product home page Git Product logo

rxjs-observed-decorator's People

Contributors

garretpremo avatar kubikowski avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

Forkers

kubikowski

rxjs-observed-decorator's Issues

Typescript 4.9.4 Breaks Decorator

Affected Versions: v1.x.x

Description:

Using the latest version of Typescript breaks how this decorator interacts with objects & their prototypes.

On initial function call, this decorator does an Object.defineProperty on the object prototype, which is passed in as target. Then, when a value is set on the object (this), it calls the prototype setter. Which in turn does a second Object.defineProperty on the object itself (this). That second Object.defineProperty is what allows individual objects to have individual BehaviorSubjects, and individual values.

But now, with Typescript 4.9.4, this interaction is broken. Typescript is overwriting the object itself (this) with the object keys that are defined on the class. So, instead of calling the prototype methods, and having getters and setters on the this object, it is running into default defined fields, which are not observed.

Example with [email protected]:

// compile time
class MyClass {
    @Observed() myString = "this is a string";
    myString$: Observable<string>;
}

// run time
{
    get myString(), // "this is a string"
    set myString(),
    get "myString$"(), // Observable<"this is a string">
    set "myString$"(),
    __proto__: {
        get myString(), // null
        set myString(),
        get "myString$"(), // Observable<null>
        set "myString$"(),
    }
}

Example with [email protected]:

// compile time
class MyClass {
    @Observed() myString = "this is a string";
    myString$: Observable<string>;
}

// run time
{
    myString: "this is a string",
    "myString$": undefined,
    __proto__: {
        get myString(), // null
        set myString(),
        get "myString$"(), // Observable<null>
        set "myString$"(),
    }
}

Steps to Reproduce:

Upgrade the dependencies of this project to the following. Then run build & test scripts.

"ts-node": "10.9.1",
"typescript": "4.9.4",

proposal: define `key + 'Event'` functions for `type: 'subject'`

Affected Versions: v2.x

Description:

Using the @Observed({ type: 'subject' }) in version 1.x is a rather clunky process, especially if that subject is of type: void. This proposes adding a defined function for @Observed({ type: 'subject' }), that can be called instead of manually setting an irrelevant next value. The function would be named as key + 'Event', similar to how we name the Observable as key + '$'.

For the rest of this feature proposal, we can use the following example:

@Observed({ type: 'subject' }) doTheThing: void;
readonly doTheThing$: Observable<void>;
readonly doTheThingEvent: () => void;

Using version 1.x, in order to push an update to that subject, we have to do the following:

this.doTheThing = null;

This proposes an added builtin function, that can be called with no arguments and will next a new observable value to the subject. This function would be called as follows in version 2.x:

this.doTheThingEvent();

Suggested Changes:

Add another Object.defineProperty() for key + 'Event', for instances of @Observed({ type: 'subject' }). The value would be defined as a function such as the following:

Object.defineProperty(target, key + 'Event', {
  value: () => subject.next(null),
});

Variants:

  1. We should consider whether this should be applied to other types of Observed subjects. For instance, should this be applied to all types, or just type: 'subject', or additionally, type: replay' but not type: 'behavior' as that already has a fully fledged behavioral suite.
  2. We could consider giving the event function an optional value argument, such as the following:
    a. key + 'Event' definition: (value?: T) => subject.next(value ?? null)
    b. api usage, given a string subject: this.myStringEvent('someString');

feat: API support `ObservedDecoratorType` or `ObservedDecoratorOptions` as arguments

Affected Versions: v1.2.x

Since this includes no breaking changes, this could be a minor release.

Description:

In addition to accepting an ObservedDecoratorOptions object argument, this would add support for accepting just a string of ObservedDecoratorType

// version 1.1.x syntax would still be supported:
@Observed({ type: 'subject' }) doTheThing: void;

// version 1.2.x syntax:
@Observed('subject') doTheThing: void;

Suggested Changes:

Add an ObservedDecoratorType type as follows, and use it as the type in ObservedDecoratorOptions:

export type ObservedDecoratorType = 'behavior' | 'subject' | 'replay';

export interface ObservedDecoratorOptions {
    type: ObservedDecoratorType;

Change the options argument on the @Observed decorator to take either ObservedDecoratorType or ObservedDecoratorOptions:

export const Observed = (options: ObservedDecoratorType | ObservedDecoratorOptions = 'behavior') => {

Does it make sense to have an Observable of the entire class?

With these decorators it becomes easy to create observable properties within a class.

But can the class itself be observable?

What that means is that if I subscribe to the class itself, I should get the whole entire class, all the properties of the class and any prototype methods. It'd likely be a BehaviourSubject since it would have a value as soon as the class is constructed.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.