Skip to content

inconsistent treatment of array map functions; revisit type signatures for functional array methods? #1701

Open
@bcolloran

Description

@bcolloran

I noticed that functions passed as arguments into Array.map are treated inconsistently depending on whether they are defined anonymously within the .map or declared elsewhere -- in the latter case, one may omit the optional arguments to the mapping function and everything works as expected. However, when a function is declared in advance, all the arguments must be explicitly included or compilation will fail.

I've included an example below that uses as-pect to test some simple functions. Uncommenting either of the first two test cases results in the following error: ERROR TS2322: Type '(~lib/string/String) => ~lib/string/String' is not assignable to type '(~lib/string/String, i32, ~lib/array/Array<~lib/string/String>) => ~lib/string/String'.

Here is an example:

function mapper(s:string): string {
  return s + "_mapped"
}

const arrowMapper = (s:string): string => s+"_mapped";

function mapper_dummyArgs(s:string,_:i32,_:string[]): string {
  return s + "_mapped"
}

const arr = ["a","b","c"]

describe("test mapping", () => {
  // // causes compilation to fail
  // it("a predefined regular function should work in an array map", ()=>{
  //   expect<string[]>(arr.map<string>(mapper)).toStrictEqual(["a_mapped","b_mapped","c_mapped"]);
  // })

  // // causes compilation to fail
  // it("a predefined arrow function should work in an array map", ()=>{
  //   expect<string[]>(arr.map<string>(arrowMapper)).toStrictEqual(["a_mapped","b_mapped","c_mapped"]);
  // })

  // this works great!
  it("an anonymous arrow function should work in an array map", ()=>{
    expect<string[]>(arr.map<string>(x=>x+"_mapped")).toStrictEqual(["a_mapped","b_mapped","c_mapped"]);
  })

  // this works great!
  it("a regular function (with dummy arguements) should work in an array map", ()=>{
    expect<string[]>(arr.map<string>(mapper_dummyArgs)).toStrictEqual(["a_mapped","b_mapped","c_mapped"]);
  })
})

I wonder if it would make sense to tweak the signatures for array methods like this to follow the JS spec (per MDN) and to make all arguments other than the first optional? I noticed that @dcodeIO made that suggestion in #514, but the decision to follow TypeScript was made instead. I totally get that following TS closely is a sensible default, however I wonder if the TS team might have simply made a small oversight WRT these signatures -- I think that it's pretty clear from the spec that the correct semantics are for the second and third argument to be optional. I think this also conforms with the great majority of usage in practice, so causing compilation to fail when dummy arguments are not explicitly declared seems undesirable?

If you are open to updating these method signatures with JS-style semantics, I'd be happy to try to put together a PR to take that chore off your plate.

Thanks!

(This is really an extension of the conversations in #449 and #514, but I wasn't sure if it would be better to resurrect those long-closed threads. Feel free to close this and reopen that if you prefer)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions