Rxjs: Create documentation for deprecations and breaking changes and add URLs messages

Created on 12 May 2019  路  17Comments  路  Source: ReactiveX/rxjs

My understanding is that in v6 and v7 there are going to be API deprecations. TSDoc decprecations have been already been added for some of these and they are causing some confusion.

For example, in this issue users of the package gained the mistaken impression that of was deprecated and in this issue, the user was unsure of what was deprecated with startWith(null). In both of these situations, the deprecation messages were due to subtleties with TypeScript's signature matching mechanism.

For contributors, it might be obvious what is and what is not deprecated, but it's understandable that users of the package might be confused by deprecation messages that are reported after a patch upgrade - particular when the deprecation message seems to related to 'normal' use.

We could make this somewhat clearer by creating a simple markdown document for each deprecation that lists what is deprecated and why and could add a link to that document in the deprecation message itself. Doing so should not require too much effort and should go some way to curtailing the opening of deprecation-related issues.

@benlesh @JWO719

docs

All 17 comments

See also this issue regarding endWith. That user was passing undefined and without strictNullChecks enabled, undefined will match the signature with the Scheduler in it.

I like the idea. If all agree to this approach I can prepare the docs site for this!

I had the same problem with startWith and didn't understand the documentation which was
deprecated startWith( scheduler: SchedulerLike): MonoTypeOperatorFunction<T> use scheduled and concatAll (e.g. scheduled([[a, b, c], source], scheduler).pipe(concatAll()))
Ended up here to figure out that it's because of the type not getting inferred. Added type like this to solve it startWith(permission.control.value as boolean).

I think the deprecation messages themselves need to be improved. Things like this keep popping up because the messages aren't sufficiently specific: https://stackoverflow.com/questions/56571406/is-the-startwith-operator-in-rxjs-really-deprecated

Also, messages should make sense when presented by a linter - not just when reading the TSDoc. For example, outside of the context of the TSDoc, this might not make much sense:

@deprecated In favor of iif creation function: import { iif } from 'rxjs';

Actually, those messages aren't too bad. TSLint reports them like this:

WARNING: .../source/...ts:29:23 - if is deprecated: In favor of iif creation function: import { iif } from 'rxjs';

Hi @cartant !

From what I understand there are the following problems:

  1. Creating a markdown document for deprecations and lists deprecations plus an explanation.
  2. Add a link to that markdown document in deprecation messages.
  3. Find ways to improve the format of depreciation linter messages.
  4. Find ways to include a link to the deprecations document in the changelog #4577

For 1 I believe this is related to #4841 with precondition of #4688

For 2 We can create a script for that. I guess @JWO719 can give details.

For 3 we could use formatter:

current styling
unstyled-linter-msg

following quick options:

  • using built-in formatters like stylish
tslint --project tsconfig.json --config tslint.json -t stylish ./index.ts

styled-linter-msg

  • or we can use custom formatters and extend stylish with links to the docs
tslint --project tsconfig.json --config tslint.json -s ./formatters -t stylishRxJS ./index.ts

custom-sytled-linter-msg

POC can be found here

For 4 we could just add another script to the tools folder that checks if there are deprecations. If yes ad the link.


Please let me know your opinion

Unfortunately, I don't think we should use a formatter.

I was not anticipating a solution requiring developers having to adjust their linting configuration and I don't think we can require them to do that.

IMO, it should report understandable messages - that include a URL - without configuration changes.

I would prefer to see a message like this:

ERROR: 3:11  deprecation  of is deprecated: passing a scheduler to of is deprecated - see https://rxjs.dev/<whatever>

where passing a scheduler to of is deprecated - see https://rxjs.dev/<whatever> is what would be in the TSDoc.

The of is deprecated part of the message is unavoidable - and unfortunate - so I think the message that follows after that is critical. It has to be succinct and understandable and, IMO, followed by a URL that links to a document with a detailed explanation of the reason for - and the implications of - the deprecation.

I had a look at your answer and a discussion with @JWO719 about the docs part.

I would do the following things:

  • [x] Create a list of all deprecations to track the progress
  • [x] I will remove api/deprecations
  • [x] In the docs guide section under to menu entry V6 I will create a new page named Deprecations
  • [x] The content has the following structure:

    • Headline follows the pattern: Deprecations introduced prior to <Version_Number> <Date>

    • Deprecation Item



      • Deprecation name


      • Reason for depreciation (whith is the token in the message from the sourcecode


      • Implications of deprecation


      • Refactoring suggestion or link to migrate scripts


      • Link to related remove section



    • Headline follows the pattern: "Breaking-changes introduced prior to "



      • Breaking Change Item


      • Name


      • Link to related deprecation



  • [x] The content fields should be in JSON format fitting the following structure:
[
  {
    type: 'deprecation' | 'breaking_change'
    name: string,
    version: string,
    date: Date,
    implications?: string,
    refactoring?: string,
    link?: string (link to deprecation or breaking_change depending on type)
  }
]
  • [ ] The created list gets checked by the team
  • [ ] I use the create list and update manually every deprecation message.
    The message has the following sections:

    • GenericDeprecationError (not customizable)
    • HumanReadebleShortMessage ( field `` )
    • LinkToDeprecationPage ( url as string )

    And follows the pattern:

    <GenericDeprecationError> <HumanReadebleShortMessage> - see <LinkToDeprecationPage>


Where <HumanReadebleShortMessage> is the section "Reason for depreciation" in the docs/

Here the first draft of the list:

deprecated in 6.0.0-beta.4 (2018-03-29)

  • [x] [never - static method - deprecated in favour of constant](https://github.com/ReactiveX/rxjs/blob/41888efcd1f34de2ee1eda0bd778d4fe0ab4263e/src/internal/observable/never.ts#L37)
  • [x] [empty - static method - depricated in favour fo constant](https://github.com/ReactiveX/rxjs/blob/69f7c6df073f5fac949e873b090746d16db787e6/src/internal/observable/empty.ts#L60)
  • [x] [WebSocketSubject - class - use deserializer in favour or resultSelector](https://github.com/ReactiveX/rxjs/blob/f5e143d7062afe743aadf0f527526c3ed383927d/src/internal/observable/dom/WebSocketSubject.ts#L105)

deprecated in 6.0.0-rc.0 (2018-03-31)

  • [x] [combineLatest - operator function - deprecated](https://github.com/ReactiveX/rxjs/blob/8fbb15e7f4b699fe5c5d10cb31bfe81595a51697/src/internal/operators/combineLatest.ts#L42)
  • [x] [merge - operator function - deprecated](https://github.com/ReactiveX/rxjs/blob/8fbb15e7f4b699fe5c5d10cb31bfe81595a51697/src/internal/operators/merge.ts#L37)
  • [x] [zip - operator function - deprecated](https://github.com/ReactiveX/rxjs/blob/8fbb15e7f4b699fe5c5d10cb31bfe81595a51697/src/internal/operators/zip.ts#L37)
  • [x] [concat - operator function - deprecated](https://github.com/ReactiveX/rxjs/blob/56cbd220dac11ec58751e15a23a56d6747964df2/src/internal/operators/concat.ts#L25)
  • [x] [concatMapTo - operator function - depricated](https://github.com/ReactiveX/rxjs/blob/41888efcd1f34de2ee1eda0bd778d4fe0ab4263e/src/internal/operators/concatMapTo.ts#L8)
  • [x] [mergeMapTo - operator function - deprecated](https://github.com/ReactiveX/rxjs/blob/26e16d7e82379cd09fc87ed1315ebd36b82d6f33/src/internal/operators/mergeMapTo.ts#L7)
  • [x] [zip - static method - no resultSelector anymore](https://github.com/ReactiveX/rxjs/blob/56cbd220dac11ec58751e15a23a56d6747964df2/src/internal/observable/zip.ts#L37)
  • [x] [switchMapTo -operator function - no resultSelector anymore](https://github.com/ReactiveX/rxjs/blob/26e16d7e82379cd09fc87ed1315ebd36b82d6f33/src/internal/operators/switchMapTo.ts#L8)
  • [x] [concatMap - operator function - no resultSelector anymore](https://github.com/ReactiveX/rxjs/blob/41888efcd1f34de2ee1eda0bd778d4fe0ab4263e/src/internal/operators/concatMap.ts#L8)
  • [x] [mergeMap - operator function - no resultSelector anymore](https://github.com/ReactiveX/rxjs/blob/41888efcd1f34de2ee1eda0bd778d4fe0ab4263e/src/internal/operators/mergeMap.ts#L16)
  • [x] [exhaustMap - operator function - no resultSelector anymore](https://github.com/ReactiveX/rxjs/blob/59b5d82cc8e19960ab1675d5e0a2da0a19c591bd/src/internal/operators/exhaustMap.ts#L16)
  • [x] [switchMap - operator function - no resultSelector anymore](https://github.com/ReactiveX/rxjs/blob/ab49acc3c1fcc74da47c5a783eb5dd957f5d63e1/src/internal/operators/switchMap.ts#L16)
  • [x] [fromEvent - static method - no resultSelector anymore](https://github.com/ReactiveX/rxjs/blob/e5ab37d0599ba94b5e7195c2f424fcc3964fbcbb/src/internal/observable/fromEvent.ts#L54)
  • [x] [fromEventPattern- static method - no resultSelector anymore](https://github.com/ReactiveX/rxjs/blob/41888efcd1f34de2ee1eda0bd778d4fe0ab4263e/src/internal/observable/fromEventPattern.ts#L9)
  • [x] [bindNodeCallback - static method - no resultSelector anymore](https://github.com/ReactiveX/rxjs/blob/41888efcd1f34de2ee1eda0bd778d4fe0ab4263e/src/internal/observable/bindNodeCallback.ts#L11)
  • [x] [bindCallback - static method - no resultSelector anymore](https://github.com/ReactiveX/rxjs/blob/056158dee33dd6c010bd303cb72cc0e82f73ed23/src/internal/observable/bindCallback.ts#L11)
  • [x] [forkJoin - static method - no resultSeletor anymore](https://github.com/ReactiveX/rxjs/blob/79261224ce85055795d2299630a744d5b3db30e8/src/internal/observable/forkJoin.ts#L40)

deprecated in 6.0.0-tactical-rc.1 (2018-04-07)

  • [x] [Scheduler - class - implement own scheduler instead ](https://github.com/ReactiveX/rxjs/blob/01a09789a0a9484c368b7bd6ed37f94d25490a00/src/internal/Scheduler.ts#L20)

deprecated in 6.1.0 (2018-05-03)

  • [x] [if - static method - renamed](https://github.com/ReactiveX/rxjs/blob/6.0.0-rc.1/src/internal/Observable.ts#L260)
  • [x] [throw - static method - renamed](https://github.com/ReactiveX/rxjs/blob/6.0.0-rc.1/src/internal/Observable.ts#L265)

deprecated in 6.2.0 (2018-05-22)

  • [x] [race - operator function - deprecated](https://github.com/ReactiveX/rxjs/blob/8f7d7fbf0ecb13b9b9f7736674796752349cb7d2/src/internal/operators/race.ts#L24)

deprecated in 6.4.0 (2019-01-30)

  • [x] [Observable - class - use an observer object instead of callbacks](https://github.com/ReactiveX/rxjs/blob/6.4.0/src/internal/Observable.ts#L78)
  • [x] [tap - operator function - use an observer object instead of callbacks](https://github.com/ReactiveX/rxjs/blob/6.4.0/src/internal/operators/tap.ts#L13)
  • [x] [create - static method - deprecated in favour of new Observable()](https://github.com/ReactiveX/rxjs/blob/6.4.0/src/internal/Observable.ts#L53)
  • [x] [timeInterval - static method - use only as interface](https://github.com/ReactiveX/rxjs/blob/6.4.0/src/internal/operators/timeInterval.ts#L70)
  • [x] [of - static method](https://github.com/ReactiveX/rxjs/blob/6.4.0/src/internal/observable/of.ts#L35)
  • [x] [of - static method](https://github.com/ReactiveX/rxjs/blob/6.4.0/src/internal/observable/of.ts#L29)
  • [x] [ObservableLike - type - deprecated](https://github.com/ReactiveX/rxjs/blob/6.3.0/src/internal/types.ts#L53-L55)

deprecated in 6.5.0 (2019-04-23)

  • [x] [combineLatest - static method - scheduler deprecated](https://github.com/ReactiveX/rxjs/blob/95bd8073e33c39a8f8d4ade8bf15c39a1154a879/src/internal/observable/combineLatest.ts#L59)
  • [x] [combineLatest - static method - resultSelector deprecated](https://github.com/ReactiveX/rxjs/blob/95bd8073e33c39a8f8d4ade8bf15c39a1154a879/src/internal/observable/combineLatest.ts#L43)
  • [x] [combineLatest - static method - multiple args as array](https://github.com/ReactiveX/rxjs/blob/95bd8073e33c39a8f8d4ade8bf15c39a1154a879/src/internal/observable/combineLatest.ts#L88)
  • [x] [partition - operator function - use static method instead](https://github.com/ReactiveX/rxjs/blob/6259f202aa26f0fec7ccadea222a3b6fcab53d46/src/internal/operators/partition.ts#L52)
  • [x] [concat - static method - derived operator from scheduled and concatAll](https://github.com/ReactiveX/rxjs/blob/56cbd220dac11ec58751e15a23a56d6747964df2/src/internal/observable/concat.ts#L17)
  • [x] [merge - static method - derived operator from scheduled and mergeAll](https://github.com/ReactiveX/rxjs/blob/b5a2ac9d3576227291238bf36244a54d9739edf6/src/internal/observable/merge.ts#L30)
  • [x] [of - static method - use scheduled](https://github.com/ReactiveX/rxjs/blob/56cbd220dac11ec58751e15a23a56d6747964df2/src/internal/observable/of.ts#L29)
  • [x] [startWith - operator function - derived operator from scheduled and concatAll](https://github.com/ReactiveX/rxjs/blob/b5a2ac9d3576227291238bf36244a54d9739edf6/src/internal/operators/startWith.ts#L19)
  • [x] [endWith - operator function - derived operator from scheduled and concatAll](https://github.com/ReactiveX/rxjs/blob/986be2f1a1186cbbd1b2dc68fe6d11ba1f32247e/src/internal/operators/endWith.ts#L29)
  • [x] [from - static method - depreacted in favour of scheduled](https://github.com/ReactiveX/rxjs/blob/b5a2ac9d3576227291238bf36244a54d9739edf6/src/internal/observable/from.ts#L7)
  • [x] [of - static method - no scheduler](https://github.com/ReactiveX/rxjs/blob/56cbd220dac11ec58751e15a23a56d6747964df2/src/internal/observable/of.ts#L35)
  • [x] [forkJoin - static method -multiple args as array](https://github.com/ReactiveX/rxjs/blob/79261224ce85055795d2299630a744d5b3db30e8/src/internal/observable/forkJoin.ts#L22)
  • [x] [concat - static method - derived operator from scheduled and concatAll](https://github.com/ReactiveX/rxjs/blob/56cbd220dac11ec58751e15a23a56d6747964df2/src/internal/observable/concat.ts#L17)
  • [x] [ObservableLike - interface - depercated](https://github.com/ReactiveX/rxjs/blob/6.4.0/src/internal/types.ts#L53-L55)

deprecated in 6.5.1 (2019-04-23)

  • [x] [NotificationKind - string litterals instead of enums](https://github.com/ReactiveX/rxjs/blob/fc9186ce5c54d14f40dbb940e868b71ddd0d6fb3/src/internal/Notification.ts#L9)

deprecated in 7.0.0-alpha.0 (2019-09-18)

  • [x] [TestScheduler -class - hot/voldObservable not for public use](https://github.com/ReactiveX/rxjs/blob/b713d39fbd740606f8cf41f6c9fb883cfc48f0c4/src/internal/testing/TestScheduler.ts#L40)
  • [x] [TestScheduler -class - hot/voldObservable not for public use](https://github.com/ReactiveX/rxjs/blob/b713d39fbd740606f8cf41f6c9fb883cfc48f0c4/src/internal/testing/TestScheduler.ts#L40)
  • [x] [VirtualTimeScheduler - class - frameTimeFactor removed in v8](https://github.com/ReactiveX/rxjs/blob/8c32ed0e0038147f40f905e41ec9b0c512e6fb32/src/internal/scheduler/VirtualTimeScheduler.ts#L8)
  • [x] [VirtualTimeScheduler - class - index removed in v8](https://github.com/ReactiveX/rxjs/blob/8c32ed0e0038147f40f905e41ec9b0c512e6fb32/src/internal/scheduler/VirtualTimeScheduler.ts#L21)

deprecated in v7.x

  • [x] [generate - static method - resultSelector needs deprecation. !!!currently missing!!!](https://github.com/ReactiveX/rxjs/blob/ba8a95fb647842e407cc68a21b6b3864ad022ed0/src/internal/observable/generate.ts#L68)

removed in v7.x

  • [x] [rxjs-compat removed here]()

removed in v8.x

  • [x] [of - static method](https://github.com/ReactiveX/rxjs/blob/56cbd220dac11ec58751e15a23a56d6747964df2/src/internal/observable/of.ts#L35)
  • [x] [TestScheduler -class - hot/voldObservable not for public use](https://github.com/ReactiveX/rxjs/blob/b713d39fbd740606f8cf41f6c9fb883cfc48f0c4/src/internal/testing/TestScheduler.ts#L40)
  • [x] [concat - static method - derived operator from scheduled and concatAll](https://github.com/ReactiveX/rxjs/blob/56cbd220dac11ec58751e15a23a56d6747964df2/src/internal/observable/concat.ts#L17)
  • [x] [VirtualTimeScheduler - class - frameTimeFactor removed in v8](https://github.com/ReactiveX/rxjs/blob/8c32ed0e0038147f40f905e41ec9b0c512e6fb32/src/internal/scheduler/VirtualTimeScheduler.ts#L8)
  • [x] [VirtualTimeScheduler - class - index removed in v8](https://github.com/ReactiveX/rxjs/blob/8c32ed0e0038147f40f905e41ec9b0c512e6fb32/src/internal/scheduler/VirtualTimeScheduler.ts#L21)

@cartant
I would need a bit of input about the grouping and reverencing them.

I would like to create a timeline that lists all deprecation by release.
If a deprecation gets removed I list the removal and a link to the deprecation with detailed instructions.

What is the best way to discover in which release the deprecation was introduced?

I went through all deprecations and found the version of the introduction.

@benlesh
Please introduce a rule that commits need to mention deprecations!
It took me forever to set up this list. Also, it will take users forever to find out what to do because even in the changelog there is nothing.

Introducing some rules to commit messages and the changelog will help everyone A LOT!

Furthermore, I suggest group similar deprecations within one release. This makes it easier in upgrading versions.

I created a first draft of the deprecation page. I would need some feedback about the content and the linking. Sometimes it is pretty repetitive content, especially in the remove sections.

Also the namings: Removed, Old usage, New usage etc are not really good.

I'm happy for every input. :)

In the following my first try:

...

Deprecations introduced prior to 2018-03-29 (6.0.0-beta.4 )

Static method never deprecated in favor of constant NEVER

| never | Breaking-Change in version 7.x |
| --- | --- |
| Reason | Deprecated because it is more efficient? Some more text here... Some more text here... Some more text here... |
| Implications | Replacing never with NEVER |

Usage <= 6.0.0-beta.3

import { never } from 'rxjs';

never();

Usage >= 6.0.0-beta.4

import { NEVER } from 'rxjs';
NEVER;

Static method empty deprecated in favor of constant EMPTY

| empty | Breaking-Change in version 7.x |
| --- | --- |
| Reason | Deprecated because it is more efficient? Some more text here... Some more text here... Some more text here... |
| Implications | Replacing empty with EMPTY |

Usage >= 6.0.0-beta.3

import { empty } from 'rxjs';
empty();

Usage >= 6.0.0-beta.4

import { EMPTY } from 'rxjs';
EMPTY;

...

Breaking-changes introduced prior to 2018-03-29 (6.0.0-beta.5)

...

...

Breaking-changes introduced prior to [unknown] (7.x)

Static method never removed

Deprecated in version 6.0.0.beta-4 see refactoring suggestions there

Static method empty removed

Deprecated in version 6.0.0.beta-4 see refactoring suggestions there

...

...

I like it. I think it will resolve a lot of confusion. If figuring out when the deprecations were added it too tedious, I'd suggest a section titled "Deprecations introduced prior to /* some date */".

I updated the draft above and used tables.

Thanks for your feedback and time! <3

I guess I have everything from the content side to start. I will discuss the rest with @JWO719 regarding the integration.

If more feedback pops up, just shoot!

@JWO719 I updated the todos with a JSON structure.
Please confirm it so I can start working on it.

The json structure looks good to me, I could imagine that this could be autogenerated at some point of time!

Exactly this is the reason I want to start with a JSON right away. :)

THX for the answer!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

giovannicandido picture giovannicandido  路  4Comments

LittleFox94 picture LittleFox94  路  3Comments

haf picture haf  路  3Comments

dooreelko picture dooreelko  路  3Comments

shenlin192 picture shenlin192  路  3Comments