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

feat(common): stricter types for SlicePipe #30156

Closed
wants to merge 1 commit into from

Conversation

cexbrayat
Copy link
Member

@cexbrayat cexbrayat commented Apr 26, 2019

Adds overloads to the transform methods of SlicePipe,
to have better types than any for value and any as a return.
With this commit, using slice in an ngFor still allow to type-check the content of the ngFor
with fullTemplateTypeCheck enabled in Ivy:

<div *ngFor="let user of users | slice:0:2">{{ user.typo }}</div>
                                                    |
                                                    `typo` does not exist on type `UserModel`

whereas it is currently not catched (as the return of slice is any) neither in VE nor in Ivy.

BREAKING CHANGE
SlicePipe now only accepts an array of values, a string, null or undefined.
This was already the case in practice, and it still throws at runtime if another type is given.
But it is now a compilation error to try to call it with an unsupported type.

PR Checklist

Please check if your PR fulfills the following requirements:

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • angular.io application / infrastructure changes
  • Other... Please describe:

What is the current behavior?

Issue Number: #30086

What is the new behavior?

The slice pipe is now properly typed, so Ivy and fullTemplateTypeCheck enabled will catch errors inside an ngFor using a slice.

Does this PR introduce a breaking change?

  • Yes
  • No

Technically this changes the API, as it was previously possible to (wrongly) call slice.transform(14, 1); which still throws at runtime but is now a compile time error.

Other information

@alxhub as we talked about it on Slack

@cexbrayat cexbrayat requested a review from a team as a code owner April 26, 2019 19:45
@cexbrayat cexbrayat force-pushed the feat/type-slice branch 2 times, most recently from 1ff3059 to a52ffb9 Compare April 26, 2019 20:40
@cexbrayat cexbrayat requested a review from a team as a code owner April 26, 2019 20:40
@@ -28,14 +28,17 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
it('should support lists', () => { expect(() => pipe.transform(list, 0)).not.toThrow(); });

it('should not support other objects',
() => { expect(() => pipe.transform({}, 0)).toThrow(); });
() => { expect(() => pipe.transform({} as string, 0)).toThrow(); });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as any would be less weird

@cexbrayat cexbrayat force-pushed the feat/type-slice branch 2 times, most recently from 06dbaa7 to 07fc080 Compare April 26, 2019 21:09
@@ -62,6 +62,10 @@ export class SlicePipe implements PipeTransform {
* - **if positive**: return all items before `end` index of the list or string.
* - **if negative**: return all items before `end` index from the end of the list or string.
*/
transform<T>(value: T[], start: number, end?: number): T[];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it should also accept ReadonlyArray<T>?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I don't know if it's best to have another overload, or if transform<T, A extends ReadonlyArray<T>>(value: A, start: number, end?: number): A; is enough...

@IgorMinar
Copy link
Contributor

if this PR presubmits without any failures in google3 which would confirm the theory that this is not a de facto breaking change then I'd be fine merging this change into the 8.0.x branch.

@IgorMinar IgorMinar added action: presubmit The PR is in need of a google3 presubmit area: common Issues related to APIs in the @angular/common package labels Apr 29, 2019
@ngbot ngbot bot added this to the needsTriage milestone Apr 29, 2019
@kara kara added the action: review The PR is still awaiting reviews from at least one requested reviewer label May 7, 2019
Copy link
Contributor

@kara kara left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Running presubmit...

@kara
Copy link
Contributor

kara commented May 7, 2019

presubmit

@kara kara added action: merge The PR is ready for merge by the caretaker target: patch This PR is targeted for the next patch release action: review The PR is still awaiting reviews from at least one requested reviewer and removed action: presubmit The PR is in need of a google3 presubmit action: review The PR is still awaiting reviews from at least one requested reviewer labels May 7, 2019
@kara
Copy link
Contributor

kara commented May 7, 2019

@IgorMinar Looks like this passed TAP in google. Are you good with merging this?

@@ -62,6 +62,10 @@ export class SlicePipe implements PipeTransform {
* - **if positive**: return all items before `end` index of the list or string.
* - **if negative**: return all items before `end` index from the end of the list or string.
*/
transform<T, A extends ReadonlyArray<T>>(value: A, start: number, end?: number): A;
Copy link
Member

@alxhub alxhub May 7, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is technically correct. ReadonlyArray<T>.slice() returns a T[] not a ReadonlyArray<T>. SlicePipe should do the same - slicing a ReadonlyArray<T> results in a T[].

That is, it should be valid in a template to write:

{{ foo(readOnly | slice:0:3) }}

Even if foo() requires an argument of T[] and readOnly is a ReadonlyArray<T>.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it could treat Array<T> and ReadonlyArray<T> as two overloads.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no real need - since slice makes a copy, it's okay to accept ReadonlyArray (a strictly narrower type than Array) and always return the mutable Array.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alxhub I updated the signature to accept ReadonlyArray<T> and return Array<T>

Copy link
Contributor

@IgorMinar IgorMinar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. Lgtm

@IgorMinar IgorMinar removed the action: review The PR is still awaiting reviews from at least one requested reviewer label May 8, 2019
@alxhub alxhub added the action: cleanup The PR is in need of cleanup, either due to needing a rebase or in response to comments from reviews label May 9, 2019
Adds overloads to the `transform` methods of `SlicePipe`,
to have better types than `any` for `value` and `any` as a return.
With this commit, using `slice` in an `ngFor` still allow to type-check the content of the `ngFor`
with `fullTemplateTypeCheck` enabled in Ivy:

    <div *ngFor="let user of users | slice:0:2">{{ user.typo }}</div>
                                                        |
                                                        `typo` does not exist on type `UserModel`

whereas it is currently not catched (as the return of `slice` is `any`) neither in VE nor in Ivy.

BREAKING CHANGE
`SlicePipe` now only accepts an array of values, a string, null or undefined.
This was already the case in practice, and it still throws at runtime if another type is given.
But it is now a compilation error to try to call it with an unsupported type.
@cexbrayat cexbrayat removed the action: cleanup The PR is in need of cleanup, either due to needing a rebase or in response to comments from reviews label May 17, 2019
@alxhub
Copy link
Member

alxhub commented May 17, 2019

Presubmit

@jasonaden jasonaden closed this in 95830ee May 17, 2019
jasonaden pushed a commit that referenced this pull request May 17, 2019
Adds overloads to the `transform` methods of `SlicePipe`,
to have better types than `any` for `value` and `any` as a return.
With this commit, using `slice` in an `ngFor` still allow to type-check the content of the `ngFor`
with `fullTemplateTypeCheck` enabled in Ivy:

    <div *ngFor="let user of users | slice:0:2">{{ user.typo }}</div>
                                                        |
                                                        `typo` does not exist on type `UserModel`

whereas it is currently not catched (as the return of `slice` is `any`) neither in VE nor in Ivy.

BREAKING CHANGE
`SlicePipe` now only accepts an array of values, a string, null or undefined.
This was already the case in practice, and it still throws at runtime if another type is given.
But it is now a compilation error to try to call it with an unsupported type.

PR Close #30156
BioPhoton pushed a commit to BioPhoton/angular that referenced this pull request May 21, 2019
Adds overloads to the `transform` methods of `SlicePipe`,
to have better types than `any` for `value` and `any` as a return.
With this commit, using `slice` in an `ngFor` still allow to type-check the content of the `ngFor`
with `fullTemplateTypeCheck` enabled in Ivy:

    <div *ngFor="let user of users | slice:0:2">{{ user.typo }}</div>
                                                        |
                                                        `typo` does not exist on type `UserModel`

whereas it is currently not catched (as the return of `slice` is `any`) neither in VE nor in Ivy.

BREAKING CHANGE
`SlicePipe` now only accepts an array of values, a string, null or undefined.
This was already the case in practice, and it still throws at runtime if another type is given.
But it is now a compilation error to try to call it with an unsupported type.

PR Close angular#30156
@cexbrayat cexbrayat deleted the feat/type-slice branch June 27, 2019 11:35
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 15, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker area: common Issues related to APIs in the @angular/common package cla: yes target: patch This PR is targeted for the next patch release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants