angular-docs-cn/aio/content/guide/migration-injectable.md

3.2 KiB

Migration to Add Missing @Injectable() Decorators

What does this schematic do?

This schematic adds an @Injectable() decorator to a class if the class has been added as a provider anywhere in the application.

An example diff might look like the following:

Before:

export class TypeCase {...}

After:

@Injectable()
export class TypeCase {...}

There are a few cases where the decorator won't be added. For example:

  • It already has another decorator such as @Component(), @Directive() or @Pipe(). These decorators already cause the compiler to generate the necessary information.
  • The provider definition has useValue, useFactory, or useExisting. In these cases, the framework doesn't need the @Injectable() decorator to create the class because because it can just use the value, factory function, or existing instance that was provided.

For example, for the following module definition, the schematic will check TypeCase, ProvideCase, ExistingClass, and SomeClass to ensure they are marked with the @Injectable() decorator and add one if not.

  @NgModule({
    providers: [
      // TypeCase needs @Injectable()
      TypeCase,
      // ProvideCase needs @Injectable()
      {provide: ProvideCase},
      // No @Injectable() needed because the value will be used
      {provide: ValueCase, useValue: 0},
      // No @Injectable() needed because factory will be used
      {provide: FactoryCase, useFactory: ()=> null},
      // ExistingClass needs @Injectable()
      {provide: ExistingToken, useExisting: ExistingClass},
      // SomeClass needs @Injectable()
      {provide: ClassToken, useClass: SomeClass},
      // No @Injectable() needed because it has a @Pipe() decorator
      PipeCase,

    ]
  })

Why is this migration necessary?

In our docs, we've always recommended adding @Injectable() decorators to any class that is provided or injected in your application. However, older versions of Angular did allow injection of a class without the decorator in certain cases, such as AOT mode. This means if you accidentally omitted the decorator, your application may have continued to work despite missing @Injectable() decorators in some places. This is problematic for future versions of Angular. Eventually, we plan to strictly require the decorator because doing so enables further optimization of both the compiler and the runtime. This schematic adds any @Injectable() decorators that may be missing to future-proof your app.

When should I be adding @Injectable() decorators to classes?

Any class that is provided or injected somewhere must have an @Injectable() decorator. The decorator is necessary for the framework to properly create an instance of that class through DI.

However, as noted above, classes that already have another class decorator like @Pipe do not need both decorators. The existing class decorator will cause the compiler to generate the proper information.

Should I update my library?

Yes, if your library has any tokens that are meant to be injected, they should be updated with the @Injectable() decorator. In a future version of Angular, a missing @Injectable() decorator will always throw an error.