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

Intersected type that is part constructor does not work #13400

Closed
shlomiassaf opened this issue Jan 10, 2017 · 2 comments
Closed

Intersected type that is part constructor does not work #13400

shlomiassaf opened this issue Jan 10, 2017 · 2 comments

Comments

@shlomiassaf
Copy link

shlomiassaf commented Jan 10, 2017

I have a small mixin helper that returns both instance and static members:

export interface Type<T> extends Function { new (...args: any[]): T; }
export type Tixin<BASE, MIXIN> = BASE & MIXIN;
export function Tixin<TBASE, CBASE, TMIXIN, CMIXIN>(base: CBASE & Type<TBASE>, mixin: CMIXIN & Type<TMIXIN>): Type<TBASE & TMIXIN> & CMIXIN & CBASE  {
  return base as any; // implementation omited
}

I "mix in" 2 classes

export class User_ {
  id: number;
  username: string;
  motto: string;
}


export class Resource<T> {
  post(): Observable<Tixin<T, Resource<T>>> {
    return null;
  }
}

// export the "class" and "type"
export const User = Tixin(User_, Resource);
export type User = Tixin<User_, Resource<User_>>;

When using, this is all valid:

new User().post().subscribe( u => u.motto && u.post().subscribe( d => d.username) );
new User().id;

let u: User = new User();
u.post().subscribe( d => u.id && d.post().subscribe(f => f.id) );
u.id;

But what I want to extend the User:

class XYZ extends User {

}

I get this error:

Type 'Type<User_ & Resource<any>> & typeof Resource & typeof User_ & ResourceStatic<User_>' is not a constructor function type. 

Type<User_ & Resource<any>> is part of the intersection which is a constructor type...

What am I missing here?

Tried on TS 2.1.4 & 2.2 dev...

@shlomiassaf
Copy link
Author

A simple example - no rxjs:

// START - MIXIN UTIL
export interface Type<T> extends Function { new (...args: any[]): T; }
export type Tixin<BASE, MIXIN> = BASE & MIXIN;
export function Tixin<TBASE, CBASE, TMIXIN, CMIXIN, SMIXIN>(base: CBASE & Type<TBASE>, mixin: CMIXIN & Type<TMIXIN>): Type<TBASE & TMIXIN> & CMIXIN & CBASE {
  // basic mixin fn, copy instance values and static values.
  Object.getOwnPropertyNames(mixin.prototype)
    .forEach(name => base.prototype[name] = mixin.prototype[name]);

  Object.getOwnPropertyNames(mixin).forEach(name => {
    if (!base.hasOwnProperty(name)) {
      base[name] = mixin[name];
    }
  });
  return base as any;
}
// END - MIXIN UTIL


// START - USAGE DEMO

/**
 * out base class, has static and instance members.
 */
class User_ {
  id: number;
  username: string;
  age: number;

  static getOne(): number {
    return 1;
  }
}

/**
 * A class to mixin into User_
 * Also has static and instance members.
 */
class Resource {
  age2: number;

  add(num: number): number {
    return num + this.age2;
  }

  static getTwo(): number {
    return 2;
  }
}

// these are the exported value and type (should mimic class that has both type and value)
export const User = Tixin(User_, Resource);
export type User = Tixin<User_, Resource>;


// now lets see in action:
let user: User = new User();
user.username = 'jd';
user.age = 30;
user.age2 = 40;
console.log(`This should be 70: ${user.add(user.age)}`);

console.log(`This should be 3: ${User.getOne() + User.getTwo()}`);

// NO TYPE ERRORS TILL THIS POINT, NO RUNTIME ERRORS TILL THIS POINT.


// ERROR IN CODE FROM THIS POINT:

class XYZ extends User { // THIS CAUSE THE ERROR: Type 'Type<User_ & Resource> & typeof Resource & typeof User_' is not a constructor function type.
  // override behavior.
  add(num: number): number {
    return this.age2 - num;
  }
}

// YET IN RUNTIME WORKS FINE:
let user2: XYZ = new XYZ();
user2.username = 'jd';
user2.age = 30;
user2.age2 = 40;
console.log(`This should be 10: ${user2.add(user2.age)}`); // 10 instead of 70
console.log(`This should be 3: ${XYZ.getOne() + XYZ.getTwo()}`); // no change

@shlomiassaf
Copy link
Author

Probably #4890

@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant