ModuleWithProviders
迁移
ModuleWithProviders
Migration
这个原理图做了什么?
What does this schematic do?
一些 Angular 库,比如 @angular/router
和 @ngrx/store
,实现了某些返回 ModuleWithProviders
类型的 API(通常是一个名叫 forRoot()
的方法)。这种类型代表了一个 NgModule
以及其提供者。Angular 9 不推荐使用不带泛型的 ModuleWithProviders
,泛型类型就是 NgModule
的类型。
Some Angular libraries, such as @angular/router
and @ngrx/store
, implement APIs that return a type called ModuleWithProviders
(typically via a method named forRoot()
). This type represents an NgModule
along with additional providers. Angular version 9 deprecates use of ModuleWithProviders
without an explicitly generic type, where the generic type refers to the type of the NgModule
.
这个原理图会给那些缺少泛型的 ModuleWithProviders
用法添加泛型类型。在下面的例子中,NgModule
的类型是 SomeModule
,所以原理图就把类型修改为 ModuleWithProviders<SomeModule>
。
This schematic will add a generic type to any ModuleWithProviders
usages that are missing the generic. In the example below, the type of the NgModule
is SomeModule
, so the schematic changes the type to be ModuleWithProviders<SomeModule>
.
以前
Before
@NgModule({...})
export class MyModule {
static forRoot(config: SomeConfig): ModuleWithProviders {
return {
ngModule: SomeModule,
providers: [
{provide: SomeConfig, useValue: config}
]
};
}
}
以后
After
@NgModule({...})
export class MyModule {
static forRoot(config: SomeConfig): ModuleWithProviders<SomeModule> {
return {
ngModule: SomeModule,
providers: [
{provide: SomeConfig, useValue: config }
]
};
}
}
在极少数情况下,原理图无法确定 ModuleWithProviders
的类型,你可能会看到原理图打印出一条 TODO 注释来让你手动更新代码。
In the rare case that the schematic can't determine the type of ModuleWithProviders
, you may see the schematic print a TODO comment to update the code manually.
为何这项迁移是必要的?
Why is this migration necessary?
自 Angular 7 开始,ModuleWithProviders
就有了泛型类型,但它是可选的。即使缺了也可以正常编译,因为 metadata.json
文件中包含了所有的元数据。在 Ivy 中,不再需要 metadata.json
文件了,所以框架不能再假定已经有了所有必要的类型。相反,Ivy 要依赖 ModuleWithProviders
的泛型类型来获取正确的类型信息。
ModuleWithProviders
has had the generic type since Angular version 7, but it has been optional. This has compiled because the metadata.json
files contained all the metadata. With Ivy, metadata.json
files are no longer required, so the framework cannot assume that one with the necessary types has been provided. Instead, Ivy relies on the generic type for ModuleWithProviders
to get the correct type information.
出于这个原因,Angular 9 版本不推荐使用不带泛型类型的 ModuleWithProviders
。Angular 的未来版本会删除默认的泛型类型,并且要求一个明确的类型。
For this reason, Angular version 9 deprecates ModuleWithProviders
without a generic type. A future version of Angular will remove the default generic type, making an explicit type required.
当我把新的 ModuleWithProviders
类型添加到应用中时,是否应该添加泛型?
Should I add the generic type when I add new ModuleWithProviders
types to my application?
是的,任何时候,当你的代码引用了 ModuleWithProviders
类型,都要有一个与其返回的实际 NgModule
相匹配的泛型类型(例如,ModuleWithProviders<MyModule>
)。
Yes, any time your code references the ModuleWithProviders
type, it should have a generic type that matches the actual NgModule
that is returned (for example, ModuleWithProviders<MyModule>
).
如果此原理图打印出了 TODO 注释,我该怎么办?
What should I do if the schematic prints a TODO comment?
此原理图会在它无法检测出 ModuleWithProviders
类型的正确泛型类型的情况下打印 TODO 注释。在这种情况下,你需要手动为 ModuleWithProviders
添加正确的泛型。它应该匹配 ModuleWithProviders
对象中返回的那个 NgModule
。
The schematic will print a TODO comment in the event that it cannot detect the correct generic for the ModuleWithProviders
type. In this case, you'll want to manually add the correct generic to ModuleWithProviders
. It should match the type of whichever NgModule
is returned in the ModuleWithProviders
object.
这对库意味着什么?
What does this mean for libraries?
库应该把泛型类型添加到 ModuleWithProviders
类型的任何一次使用中。
Libraries should add the generic type to any usages of the ModuleWithProviders
type.
那些使用未迁移库的应用呢?
What about applications using non-migrated libraries?
Angular 兼容性编译器 ( ngcc
)会自动转换所有未迁移的库来生成合适的代码。
The Angular compatibility compiler (ngcc
) should automatically transform any non-migrated libraries to generate the proper code.