Git Product home page Git Product logo

polytype's People

Contributors

fasttime avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

polytype's Issues

Improving typing for getPrototypeListOf

I was using super.class(BaseClass) in may cases and it handles typing correctly.
I see: protected class<U extends T>(type: U): U; in the .d.ts file

I was trying out getPrototypeListOf and realized that I was getting all the baseClass as any
And I saw: export function getPrototypeListOf(o: any): any[]; in the .d.ts file
So, creating this issue to potentially improve the typing here to get more accurate types

PS: I have no idea if it is possible at all :)

I did try this:

export class ChildClass extends classes(BaseClass1, BaseClass2) {
    myFunc() {
        (getPrototypeListOf(ChildClass) as (BaseClass1 | BaseClass2)[]).forEach(baseClass => {
            baseClass.myFunc()
        })
    }
}

NOTE: This will assume baseClass has the type (typeof BaseClass1 | typeof BaseClass2)
So, if all my base classes implement a particular function - then this work out quite well

Doing: getPrototypeListOf(ChildClass) as [BaseClass1, BaseClass2] would also work and be more accurate

Issue with Angular 8 in prod mode

When we launch the following command:
ng serve --prod --source-map

We get the following error:

ERROR in main.d558a3403cc855f52798.js from Terser
Unexpected token: punc ()) [./node_modules/polytype/lib/polytype.mjs:117,0][main.d558a3403cc855f52798.js:52044,4]

Using generic in baseclass

Hi, I am working on an angular project which uses typescript and was trying to use polytype.
I have a case where I am trying to use polytype in something like:

class WriteService<T> {
    create(t: T): T;
    update(t: T): T;
}

export class UserService extends WriteService<UserModel> {
    ...
}

i.e. my BaseService is defining a bunch of functions for my Type - and then I inherit this into a UserService with my UserModel.

When I try to use polytype:

export class UserService extends classes(WriteService<UserModel>) {
    ...
}

it gives me an error - so, I tried a few variations of this (without much understanding of the magic polytype does), but was not able to figure out how to handle this case with polytype.

Some variations I tried:

  • Sending as a generic: export class UserService<T> extends classes(WriteService<T>)
  • Giving classes an explicit type: export class UserService extends classes<[WriteService<UserModel>]>(WriteService)
  • Giving classes an explicit type: export class UserService extends classes<[typeof WriteService<UserModel>]>(WriteService)

I guess the argument to classes is a class. So, I can't pass the <> there... ?

Comparing polytype with other methods

I've been trying to figure out inheritance / mixin approach for the past few days.
And I've seen a few methods around

polytype seems to be the most robust approach I have come acorss based on the documentation so far.
I was wondering if there was some nice comparison of some of the common approaches and pitfalls or other approaches that could exist ?

For example -

  1. The single inheritance available in JS now prototype replacement (which does not allow multiple inheritance)
  2. The approach of modifying the prototype of classes - like Object.assign(MyClass.prototype, MyMixin); (which does not allow me to use super(), instanceof, doesnt handle typing, etc.)
  3. The approach mentioned in typescript's mixin documentation right now about dynamic classes inherited in a function (Which has a bit of an awkward syntax ? But seems to handle everything else ?)
  4. ts-mixer

And so on.

explicit classes export

Hi

In general manipulating global isn't a good idea (in some cases it does have value, so won't argue that) and it would be safer if we can just

// explicit usage
import { classes } from 'polytype';

// global usage
import defineGlobally from 'polytype';
defineGlobally();
// or 
import 'polytype/global';

Issue with ngOnDestry method when use polytype

I have a component that navigate to other page when finish the method ngOnInit:

import { Component, OnInit } from '@angular/core';
import { ClassA } from './classA';
import { ClassB } from './classB';
import { classes } from 'polytype';
import { ClassAService} from './classA.service';
import { ClassBService} from './classB.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.sass']
})
export class AppComponent extends classes(ClassA, ClassB)  {

  constructor(
    classAService: ClassAService,
    classBService: ClassBService
) {
    super(['classAService'], ['classBService']);
  }

  ngOnInit(): void {
    // Do something and navigate to other page
  }
}

The issue come when both extended classes have ngOnDestroy method, only the first class execute ngOnDestroy and should both classes execute It. I need to do the following to make it works correctly but I think It is not the best option:

 ngOnInit(): void {
    // Navigate to other page
   super.class(ClassB).ngOnDestroy();
  }

Thank you for your great work I look forward to your answer.

Abstract Class Support

Hey

I was trying to use this library to do something a tad bit weird and ran into an error.

Cannot assign an abstract constructor type to a non-abstract constructor type

To recreate the bug

abstract class AbstractClass {}

class Test extends classes(AbstractClass) {}
// Argument of type 'typeof AbstractClass' is not assignable to parameter of type 'SuperConstructor'.
//  Cannot assign an abstract constructor type to a non-abstract constructor type.ts(2345)

Not sure if this is just a typing bug, ie the package supports abstract classes but the types have to be updated or if they package itself doesn't have abstract class support

Issue with Angular module

When i use Polytype with Angular 8 i get this error:

Unexpected value 'AppComponent' declared by the module 'AppModule'

AppComponent:

import { Component, OnInit } from '@angular/core';
import { ClassA } from './classA';
import { ClassB } from './classB';
import { classes } from 'polytype';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.sass']
})
export class AppComponent extends classes(ClassA, ClassB) implements OnInit  {

  constructor() {
    super(['hola'], ['adios']);
  }

  ngOnInit(): void {
    this.printA();
    this.printB();
  }
}

AppModule

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

If I delete extends classes(ClassA, ClassB) everything works correctly

core.js:4117 ERROR TypeError: Constructor cannot be invoked without 'new'

Hi,
I have created a simple angular-9 component and attempt to use polytype to extend a typescript Utils class.

I am using the following packages:

  • "@angular/cli": "^9.1.7"
  • "typescript": "3.8.3"
  • "polytype": "^0.9.4",
import {  Component,  OnInit,} from '@angular/core'
import { NgControl } from '@angular/forms'
import { classes } from 'polytype'

export class Utils {
//  constructor() {} - does not work either if uncommented
  
  onFocusInShowPendingValidationStatus( validationStatus: string, evernt?: Event ): string {
    return validationStatus = 'pending'
  }
  
  onFocusOutValidationStatus( validationStatus: string, control: NgControl, event?: Event ): string {
    return validationStatus = control.valid ? 'valid' : 'invalid'
  }
  
  onValueChangedValidationStatus( validationStatus: string, control: NgControl, event? ): string {
    return validationStatus = control.valid ? 'valid' : 'invalid'
  }
}

@Component(
    {
      selector: 'pim-poly-types',
      template: `
        <p>
          poly-types works!
        </p>
      `,
      styles: [],
    } )
export class PolyTypesComponent extends classes( Utils ) implements OnInit {
  
  constructor() {super() }
  
  ngOnInit(): void {
  }
}

However, I am consistently getting the following error that prevents the app from running. The app does compile though.

core.js:4117 ERROR TypeError: Constructor cannot be invoked without 'new' at Object.apply (polytype.mjs:43) at new PolyTypesComponent (poly-types.component.ts:36) at NodeInjectorFactory.PolyTypesComponent_Factory [as factory] (poly-types.component.ts:39) at getNodeInjectable (core.js:3956) at instantiateAllDirectives (core.js:8407) at createDirectivesInstances (core.js:7774) at ɵɵelementStart (core.js:14518) at Module.ɵɵelement (core.js:14569) at LoginFormComponent_Template (login-form.component.html:85) at executeTemplate (core.js:7747) defaultErrorLogger @ core.js:4117 push.../../node_modules/@angular/core/__ivy_ngcc__/fesm5/core.js.ErrorHandler.handleError @ core.js:4165 (anonymous) @ core.js:29098 push.../../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke @ zone.js:386 push.../../node_modules/zone.js/dist/zone.js.Zone.run @ zone.js:143 push.../../node_modules/@angular/core/__ivy_ngcc__/fesm5/core.js.NgZone.runOutsideAngular @ core.js:28074 push.../../node_modules/@angular/core/__ivy_ngcc__/fesm5/core.js.ApplicationRef.tick @ core.js:29098 (anonymous) @ core.js:28954 push.../../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke @ zone.js:386 onInvoke @ core.js:28134 push.../../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke @ zone.js:385 push.../../node_modules/zone.js/dist/zone.js.Zone.run @ zone.js:143 push.../../node_modules/@angular/core/__ivy_ngcc__/fesm5/core.js.NgZone.run @ core.js:28029 next @ core.js:28953 schedulerFn @ core.js:25506 push.../../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.__tryOrUnsub @ Subscriber.js:192 push.../../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.next @ Subscriber.js:130 push.../../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber._next @ Subscriber.js:76 push.../../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next @ Subscriber.js:53 push.../../node_modules/rxjs/_esm5/internal/Subject.js.Subject.next @ Subject.js:47 push.../../node_modules/@angular/core/__ivy_ngcc__/fesm5/core.js.EventEmitter.emit @ core.js:25488 checkStable @ core.js:28084 onHasTask @ core.js:28148 push.../../node_modules/zone.js/dist/zone.js.ZoneDelegate.hasTask @ zone.js:441 push.../../node_modules/zone.js/dist/zone.js.ZoneDelegate._updateTaskCount @ zone.js:462 push.../../node_modules/zone.js/dist/zone.js.Zone._updateTaskCount @ zone.js:284 push.../../node_modules/zone.js/dist/zone.js.Zone.runTask @ zone.js:205 drainMicroTaskQueue @ zone.js:601 push.../../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask @ zone.js:507 invokeTask @ zone.js:1671 globalZoneAwareCallback @ zone.js:1697 core.js:4117 ERROR Error: Uncaught (in promise): TypeError: Constructor cannot be invoked without 'new' TypeError: Constructor cannot be invoked without 'new' at Object.apply (polytype.mjs:43) at new PolyTypesComponent (poly-types.component.ts:36) at NodeInjectorFactory.PolyTypesComponent_Factory [as factory] (poly-types.component.ts:39) at getNodeInjectable (core.js:3956) at instantiateAllDirectives (core.js:8407) at createDirectivesInstances (core.js:7774) at ɵɵelementStart (core.js:14518) at Module.ɵɵelement (core.js:14569) at LoginFormComponent_Template (login-form.component.html:85) at executeTemplate (core.js:7747) at resolvePromise (zone.js:832) at resolvePromise (zone.js:784) at zone.js:894 at ZoneDelegate.push.../../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:421) at Object.onInvokeTask (core.js:28122) at ZoneDelegate.push.../../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:420) at Zone.push.../../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:188) at drainMicroTaskQueue (zone.js:601) at ZoneTask.push.../../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask [as invoke] (zone.js:507) at invokeTask (zone.js:1671) defaultErrorLogger @ core.js:4117 push.../../node_modules/@angular/core/__ivy_ngcc__/fesm5/core.js.ErrorHandler.handleError @ core.js:4165 next @ core.js:28692 schedulerFn @ core.js:25506 push.../../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.__tryOrUnsub @ Subscriber.js:192 push.../../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.next @ Subscriber.js:130 push.../../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber._next @ Subscriber.js:76 push.../../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next @ Subscriber.js:53 push.../../node_modules/rxjs/_esm5/internal/Subject.js.Subject.next @ Subject.js:47 push.../../node_modules/@angular/core/__ivy_ngcc__/fesm5/core.js.EventEmitter.emit @ core.js:25488 (anonymous) @ core.js:28157 push.../../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke @ zone.js:386 push.../../node_modules/zone.js/dist/zone.js.Zone.run @ zone.js:143 push.../../node_modules/@angular/core/__ivy_ngcc__/fesm5/core.js.NgZone.runOutsideAngular @ core.js:28074 onHandleError @ core.js:28157 push.../../node_modules/zone.js/dist/zone.js.ZoneDelegate.handleError @ zone.js:390 push.../../node_modules/zone.js/dist/zone.js.Zone.runGuarded @ zone.js:157 _loop_1 @ zone.js:701 api.microtaskDrainDone @ zone.js:708 drainMicroTaskQueue @ zone.js:608 push.../../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask @ zone.js:507 invokeTask @ zone.js:1671 globalZoneAwareCallback @ zone.js:1697

empty catch block - not accepted by some linters

theres an empty catch block in polytype.cjs file at line 526, it works fine without issues but some linters are now allowing it to be uploaded to proxy repos. can we add a simple command to handle the exception?

polytype extended class properties not behaving as typescript extended class propeties

Hi,
I am trying to use polytype in my angular9/typescript project

Consider the following code for single class inheritance in typescript:

export class AbstractBaseComponent{
form: FormGroup
}


@Component ({
   selector: 'pim'
   template: `
  <form [formGroup] = 'form'>

   </form>
`

})
export class PimComponent extends AbstractBaseComponent {
// the form of the template is referenced by the form of the Abstract
BaseComponent as expected

}

For polytype multi-inheritance

@Component ({
   selector: 'pim'
   template: `
  <form [formGroup] = 'form'>

   </form>
`

})
export class PimComponent extends classes(AbstractBaseComponent) {
// the form of the template is NOT referenced by the form of the AbstractBaseComponent as expected

}

What am I doing incorrectly. My Webstorm IDE flag the template form as error (Is this IDE failure or polytype failure?)

Thanks for your help

Bind methods problem

Hi Francesco!

Thank you for Polytype, it's very well done and carefully explained. 😃

I'm experiencing the following issue, when dealing with binds in base classes.
If I use only extends in this scenario it works as expected.

import { classes } from 'js/polytype'

class TestDefault {
    constructor() {
        this.print = this.print.bind(this)

        console.log('TestDefault constructor')
    }

    print() {
        console.log('TestDefault Print')
    }
}

class Test extends classes(TestDefault) {
    constructor() {
        super()

        this.someVar = 6

        console.log('Test constructor')
    }

    print() {
        console.log('Test Print', this.someVar)

        super.print()
    }
}

const test = new Test()

test.print()

This will print:

TestDefault constructor
Test constructor
Test Print undefined
TestDefault Print

Instead of Test Print undefined, it should be be Test Print 6.

I'm guessing the binding only binds the instance of TestDefault.
I've tried to bind again print in Test, but nothing changed.

Do you know what can be done to solve this?

Thank you!

Method override does not work correctly with "crocks" library

Steps to reproduce:

const Arrow = require("crocks/Arrow");

class K extends classes(Arrow, Object) {
  compose(...args) {
    console.log("THIS WILL NOT RUN");
    return super.compose(...args);
  }
}

const k = new K([x => x]);
const l = new K([x => x]);
k.compose(l);  // returns an instance of Arrow but no console.log

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.