angular-cli
angular-cli copied to clipboard
`Rule` from `@angular-devkit/schematics` should accept return type `Promise<Tree>`
🚀 Feature request
Rule
from @angular-devkit/schematics
should accept return type Promise<Tree>
Command (mark with an x
)
- [ ] new
- [ ] build
- [ ] serve
- [ ] test
- [ ] e2e
- [ ] generate
- [ ] add
- [ ] update
- [ ] lint
- [ ] extract-i18n
- [ ] run
- [ ] config
- [ ] help
- [ ] version
- [ ] doc
- [x] other: compiling custom schematics that depend on
@angular-devkit/schematics
Description
The interface Rule
from @angular-devkit/schematics
should accept the return type Promise<Tree>
for asynchronous schematics. Now it only accepts Observable<Tree>
:
https://github.com/angular/angular-cli/blob/37a06a7c37f5b4286d58b475e6e12c86f00fac5b/packages/angular_devkit/schematics/src/engine/interface.ts#L234-L237
The current problem with Rule
accepting only Observable<Tree>
it that it accepts only the Observable
from rxjs of a fixed version 6.6.7
(at the moment of writing) which is hardcoded in dependencies
in package.json
of @angular-devkit/schematics
:
https://github.com/angular/angular-cli/blob/c2737dd51ab68a538a317fc0d7a377032d346b53/packages/angular_devkit/schematics/package.json#L20
Therefore, if I'm writing custom schematics in my repo, while having any slightly different version of rxjs
installed, e.g. 6.6.3
, then I get an error about incompatible variants of the interface Subscriber
- between my installed version in node_modules
and the fixed version from node_modules/@angular-devkit/core/node_modules/rxjs
(which is derived from the interface Rule
)
Example of custom schematics for minimal reproduction:
import { Rule, Tree } from '@angular-devkit/schematics';
import { of } from 'rxjs';
export function migrate(): Rule {
return (tree: Tree) => {
return of(tree);
};
}
The error message in detail:
(parameter) _context: SchematicContext
Type '(tree: Tree, _context: SchematicContext) => Observable<Tree>' is not assignable to type 'Rule'.
Type 'Observable<Tree>' is not assignable to type 'void | Rule | Tree | Observable<Tree> | Promise<void | Rule>'.
Type 'import("/Users/krzysztof/code/develop-ng13/node_modules/rxjs/internal/Observable").Observable<import("/Users/krzysztof/code/develop-ng13/node_modules/@angular-devkit/schematics/src/tree/interface").Tree>' is not assignable to type 'import("/Users/krzysztof/code/develop-ng13/node_modules/@angular-devkit/core/node_modules/rxjs/internal/Observable").Observable<import("/Users/krzysztof/code/develop-ng13/node_modules/@angular-devkit/schematics/src/tree/interface").Tree>'.
The types of 'source.operator.call' are incompatible between these types.
Type '(subscriber: import("/Users/krzysztof/code/develop-ng13/node_modules/rxjs/internal/Subscriber").Subscriber<any>, source: any) => import("/Users/krzysztof/code/develop-ng13/node_modules/rxjs/internal/types").TeardownLogic' is not assignable to type '(subscriber: import("/Users/krzysztof/code/develop-ng13/node_modules/@angular-devkit/core/node_modules/rxjs/internal/Subscriber").Subscriber<any>, source: any) => import("/Users/krzysztof/code/develop-ng13/node_modules/@angular-devkit/core/node_modules/rxjs/internal/types").TeardownLogic'.
Types of parameters 'subscriber' and 'subscriber' are incompatible.
Type 'import("/Users/krzysztof/code/develop-ng13/node_modules/@angular-devkit/core/node_modules/rxjs/internal/Subscriber").Subscriber<any>' is not assignable to type 'import("/Users/krzysztof/code/develop-ng13/node_modules/rxjs/internal/Subscriber").Subscriber<any>'.
Property 'isStopped' is protected but type 'Subscriber<T>' is not a class derived from 'Subscriber<T>'.
Describe the solution you'd like
- expose
Promise<Tree>
as a return type ofRule
Describe alternatives you've considered
- workaround on my side: return
Promise<Rule | void>
instead ofPromise<Tree>
- workaround on Angular's side: move
rxjs
fromdependencies
topeerDependencies
inpackage.json
of@angular-devkit/schematics
and relax the version to^6.6.0
(but still.. what if somebody is using rxjs7 in their repo?) - I'm opened to your other suggested ideas or workarounds
This feature request is now candidate for our backlog! In the next phase, the community has 60 days to upvote. If the request receives more than 20 upvotes, we'll move it to our consideration list.
You can find more details about the feature request process in our documentation.
I'm currently working rxjs 7.5+ and my schematics build broke because of this dependency. It should have the rxjs peerDependency which supports both v6 and v7:
"peerDependencies": {
"rxjs": "^6.5.3 || ^7.4.0",
"zone.js": "~0.11.4"
},
Taken from @angular/[email protected]
package.json
Just a heads up that we kicked off a community voting process for your feature request. There are 20 days until the voting process ends.
Find more details about Angular's feature request process in our documentation.
Taking a quick look at this, it seems that the problem is more with mismatch between the schematics' Observable
type and the @angular-devkit/schematics
Observable
return type. Proper solution is probably to convert the return type to use Subscribable<T>
, and separately we should maybe look into finding ways to dedupe RxJS dependencies in the project.