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

Won't get build passed when generic type parameter exists in constructor #29899

Closed
ah787264643 opened this Issue Apr 15, 2019 · 7 comments

Comments

Projects
None yet
3 participants
@ah787264643
Copy link

ah787264643 commented Apr 15, 2019

First, the code:

export class BasicParent<T extends BaseService>{
  constructor(protected service: T, private injector?: Injector ) {
  }
}

this code won't build, say ERROR in : Can't resolve all parameters for BasicParent in /app/class/basic-parent.ts: (?, [object Object]).
such generic parameter can not be used in constructor in Angular?

@trotyl

This comment has been minimized.

Copy link
Contributor

trotyl commented Apr 16, 2019

In DI concept, the code:

@Injectable()
class MyInjectable {
  constructor(whatever: Whatever) {
    console.log(whatever)
  }
}

is equivalent to:

@Injectable()
class MyInjectable {
  constructor(injector: Injector) {
    const whatever = injector.get(Whatever)
    console.log(whatever)
  }
}

Namely Whatever here must be a value, not only a type. And clearly the T in your example is not a value, and you can never pass it to Injector.

@ah787264643

This comment has been minimized.

Copy link
Author

ah787264643 commented Apr 16, 2019

In DI concept, the code:

@Injectable()
class MyInjectable {
  constructor(whatever: Whatever) {
    console.log(whatever)
  }
}

is equivalent to:

@Injectable()
class MyInjectable {
  constructor(injector: Injector) {
    const whatever = injector.get(Whatever)
    console.log(whatever)
  }
}

Namely Whatever here must be a value, not only a type. And clearly the T in your example is not a value, and you can never pass it to Injector.

In my constructor, service is definitely a value and T is a type, same as your constructor. T is a generic type which is the only difference compared to type Whatever. Is it too strict of ng build --prod to constructors ? I am not intended to pass T to injector, just want to generate a serivice in parent class so that it is not necessary to do so in subclasses .

@trotyl

This comment has been minimized.

Copy link
Contributor

trotyl commented Apr 16, 2019

In my constructor, service is definitely a value and T is a type, same as your constructor.

No, the BaseService is only a type here (even it can be used as value), you can checked the emitted JavaScript, there's no trace of BaseService.

@ah787264643

This comment has been minimized.

Copy link
Author

ah787264643 commented Apr 16, 2019

In my constructor, service is definitely a value and T is a type, same as your constructor.

No, the BaseService is only a type here (even it can be used as value), you can checked the emitted JavaScript, there's no trace of BaseService.

BaseService following the class name is just used to indicate the scope of type T, I guess it may be gone after compiling (I call it compiling... ), is this 'bug' of javascript ?
It is OK to do so in Java, and it is OK for idea with no warning at all...
Is there a way to make it work?

@trotyl

This comment has been minimized.

Copy link
Contributor

trotyl commented Apr 16, 2019

BaseService following the class name is just used to indicate the scope of type T, I guess it may be gone after compiling (I call it compiling... ), is this 'bug' of javascript ?

It's the expected behavior, the constructor parameter types (technically also decorated property types) are exception set by emitDecoratorMetadata option in TypeScript. The emission is very limited and only works with direct class reference:

https://github.com/Microsoft/TypeScript/search?q=emitDecoratorMetadata&type=Issues

@alxhub

This comment has been minimized.

Copy link
Contributor

alxhub commented Apr 16, 2019

Yep, this is the expected behavior.

When Angular is compiling BasicParent, it needs to know what type to inject for the first constructor parameter. T doesn't suffice - it needs to either have a concrete class or an @Inject with a DI token.

@alxhub alxhub closed this Apr 16, 2019

@ah787264643

This comment has been minimized.

Copy link
Author

ah787264643 commented Apr 17, 2019

Yep, this is the expected behavior.

When Angular is compiling BasicParent, it needs to know what type to inject for the first constructor parameter. T doesn't suffice - it needs to either have a concrete class or an @Inject with a DI token.

It works , @Inject with a DI token, thanks a lot guys. @trotyl @alxhub

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.