Skip to content

Mithril not support TypeScript generated classes. #733

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

Closed
LabEG opened this issue Jul 24, 2015 · 9 comments
Closed

Mithril not support TypeScript generated classes. #733

LabEG opened this issue Jul 24, 2015 · 9 comments

Comments

@LabEG
Copy link
Contributor

LabEG commented Jul 24, 2015

Mithril not support TypeScript generated classes in components.
TypeScript generate nex class:

 var ApplicationController = (function () {
    function ApplicationController() {
    }
    ApplicationController.prototype.changeApp = function (newApp) {
        console.log('Launch app: ', newApp);
        config_1.Config.app = newApp;
        m.redraw();
    };
    return ApplicationController;
})();

But in conmponent view i have empty cotroller =\

I found next block of code

 function parameterize(component, args) {
        var controller = function() {
            console.log('777777777777777777777777777777777777777777', component.controller, (component.controller || noop).apply(this, args) || this);
            return (component.controller || noop).apply(this, args) || this
        }
        var view = function(ctrl) {
            if (arguments.length > 1) args = args.concat([].slice.call(arguments, 1))
            return component.view.apply(component, args ? [ctrl].concat(args) : [ctrl])
        }
        view.$original = component.view
        var output = {controller: controller, view: view}
        if (args[0] && args[0].key != null) output.attrs = {key: args[0].key}
        return output
    }
    m.component = function(component) {
        return parameterize(component, [].slice.call(arguments, 1))
    }

In log i have: first - is my controller, second - is empty cobntroller =\

If make this class:

var ApplicationController = (function () {
    function ApplicationController() {
        this.changeApp = function (newApp) {
            console.log('Launch app: ', newApp);
            config_1.Config.app = newApp;
            m.redraw();
        };
    }
    return ApplicationController;
})();

then work fine

@Naddiseo
Copy link
Contributor

Duplicate of #618 (and #735)?

@dead-claudia
Copy link
Member

This is a duplicate of #735 (although mine is a little more specific and more easily testable). It is not a duplicate of #618, since that's more of a suggested API change as opposed to a simple bug about the documented API vs behavior with ES6 classes (which TypeScript aims to be identical to).

@Naddiseo
Copy link
Contributor

@IMPinball, #618 is a bug about m.component/parametize not handling ES2015 classes (no matter where they're from), which is exactly what this bug is.

@dead-claudia
Copy link
Member

@Naddiseo You are correct in that the original bug was about this very thing. The conversation, though, immediately diverged to a proposal originally on Gitter (and that was what I was referencing), and there's no hope of getting that back to the original problem. Also, when people initially tried working on it, the proposal hadn't yet solidified.

@daslicht
Copy link

Was that meanwhile fixed ?

@dead-claudia
Copy link
Member

@daslicht Unless you're compiling to ES2015, the original bug should be fixed.

As for the current TypeScript type, the controller type technically should be this when targeting ES2015 (not yet safe to do so for browsers, if you're developing for the open web):

type ControllerFunction<T> = ((...args: any[]) => T) & (new (...args: any[]) => T);

But that would break a lot of existing code, simply because of the intersection type. I'm glad we're catching it now, when a large chunk of browsers still don't yet enable it by default, instead of a couple years down the road, when IE is obsolete, and 99% of clients that can run JS fully support ES2015.

@dead-claudia
Copy link
Member

And for everyone else here:

If you are curious about a long-term solution, and/or have any input/opinions on how it should be done, please check out #994.

Closing for now. Please do notify me if it's not fixed and/or the TS definition file is wrong. I'm actively working on other corrections within it ATM, so that'll be added to the list of changes I need to make.

@pdfernhout
Copy link
Contributor

Here is an example of how I dealt with the TypeScript class issue with Mithril by adding static controller and view methods to a TypeScript class:
https://github.com/pdfernhout/narrafirma/blob/master/webapp/source/applicationWidgets/StoryBrowser.ts

class StoryBrowser {
     ...
    static controller(args) {
        return new StoryBrowser(args);
    }

    static view(controller, args) {
        return controller.calculateView(args);
    }
    ...

A little convoluted, but it works.

In general, I feel there is too much magic in how Mithril makes components which has led to confusion compared to just expecting each component to have a view or render method or be a function that returns a vdom (like discussed in issue #499) and/or having the developer manage the lifestyle of components like Maquette vdom expects. But, in any case, the above design pattern worked for me for making Mithril components in TypeScript.

@LabEG
Copy link
Contributor Author

LabEG commented Mar 27, 2016

I just use next variant:

const shellComponents: Mithril.Component<ShellController> = {
    controller: (): ShellController => new ShellController(),
    view: ShellControllerView
};

This method more universal, because allows using difference views and controllers in one components.

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

No branches or pull requests

5 participants