Skip to content

Array::reverse returns generic-sized array for tuples #13360

Closed

Description

TypeScript Version: 2.1.1

Code

const original: [number, number] = [1, 0];
// Type 'number[]' is not assignable to type '[number, number]'
const reversed: [number, number] = original.reverse();

Expected behavior:

original.reverse() should be considered to be [number, number].

Actual behavior:

original.reverse() is considered to be number[].

The problem is in lib.d.ts, where reverse() returns T[].
One potential fix could be to change it to return this the way sort(...) does, but that would result in the same issues with sort pointed out in 11924#issuecomment-269055091.

// Pretend `reverse()` returns `this`:
const original: [1, 0] = [1, 0];
const inaccurate: [1, 0] = original.reverse();
// Type '[1, 0]' is not assignable to type '[0, 1]'
const accurate: [0, 1] = original.reverse();

Activity

  1. changed the title [-]Array::reverse returns generic-sized array no matter what[/-] [+]Array::reverse returns generic-sized array for tuples[/+] on Jan 9, 2017
  2. aluanhaddad commented on Jan 9, 2017

    @aluanhaddad
    Contributor

    In #11924 Tom Crockett (@pelotom) goes on to say

    It makes no sense to sort a tuple.

    I'm not convinced this is true, it might make sense. However, once sorted, treating it as tuple definitely makes no sense. I think reverse is correct and sort is the issue.

  3. JoshuaKGoldberg commented on Jan 9, 2017

    @JoshuaKGoldberg
    ContributorAuthor

    It makes no sense to sort a tuple
    I think reverse is correct and sort is the issue

    I don't think it's the responsibility of the language to dictate what subset of available features its data types are used for. TypeScript in particular has the dual task of both being a real programming language and representing JavaScript in all its peculiarities. If it's possible and reasonable to do something in JavaScript, TypeScript is generally tasked with accurately reflecting that behavior.
    Tuples are really just arrays of known length. It's completely reasonable that someone would both know the length of their arrays and that they want to reverse or sort them.

  4. pelotom commented on Jan 9, 2017

    @pelotom

    Aluan Haddad (@aluanhaddad) Both sort() and reverse() are problematic with tuples because of their side-effectful nature. A proper typing of these methods requires a typing rule that allows a method to change the type of its target in the scope in which it was invoked, after the point of invocation.

    Josh Ghoulberg 👻 (@JoshuaKGoldberg) in the absence of the perfect type system that can express exactly what happens when you side-effectfully reverse or sort a heterogeneous array of known length (when does anyone ever do this on purpose btw?), should these operations still be available and assigned a completely erroneous type? Or is it better to err on the side of safety and lose those capabilities? All type systems disallow some programs which are perfectly correct, and the task is to find the happy medium.

  5. RyanCavanaugh commented on Jan 9, 2017

    @RyanCavanaugh
    Member

    This isn't safe. The problem is that tuples can be aliased to longer tuples:

    let x: [number, string, number];
    x = [0, 'ok', 12, 'jk']; // intended: allowed
    x = x.reverse(); // proposed: allow this
    x[0]; // 'jk', not number
  6. JoshuaKGoldberg commented on Jan 9, 2017

    @JoshuaKGoldberg
    ContributorAuthor

    👍

  7. locked and limited conversation to collaborators on Jun 19, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Working as IntendedThe behavior described is the intended behavior; this is not a bug

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions