5

I tried mapping a TypeScript Tuple into another Tuple using Array.map like so:

const tuple1: [number, number, number] = [1, 2, 3];
const tuple2: [number, number, number] = tuple1.map(x => x * 2);
console.log(tuple2);

TypeScript Playground Example

But the typescript compiler is telling me this is not possible:

Type 'number[]' is not assignable to type '[number, number, number]'.
Target requires 3 element(s) but source may have fewer.

Is there a clean way to map a tuple into a new tuple without using Array.map or a way to use Array.map that the compiler does understand?

4
  • tuple1.map(x => x * 2) as [number, number, number];, but that's not ideal I guess? :) Commented Dec 17, 2020 at 7:04
  • 1
    Discovered that one already indeed. But that's cheating the compiler ;-) Commented Dec 17, 2020 at 7:06
  • Take a look at how it's done in fp-ts. There's a Tuple module where you can do const z: [number,number,number] = pipe(x, tuple.map(x => x*2)) with no problems. Or const z: [number,number,number] = tuple.map<number>(x => x*2)(x) It's probably done with declare function overloads. Commented Dec 17, 2020 at 7:12
  • Interesting, will have a look at fp-ts @user1713450 ! Commented Dec 17, 2020 at 7:29

1 Answer 1

2

TypeScript currently lacks suitable tuple method overload definitions for map inside Array.

You can globally augment the Array type declaration like this:

// important: put Array augmentation in a script/non-module file without import/export
interface Array<T> {
    // T[] | [T] enforces a tuple type.
    // {[K in keyof this]: U} keeps a mapped tuple type.
    map<U>(callbackfn: (value: T, index: number, tuple: T[] | [T]) => U, thisArg?: any): {[K in keyof this]: U}
}
const t1: [number, number] = [1, 2];
const t1M = t1.map(x => x * 2); // t1M: [number, number]
const t2: [number, number, number] = [1, 2, 3];
const t2M = t2.map(String); // t2M: [string, string, string]

const t3: number[] = [1, 2, 3]
const t3M = t3.map(x => x * 2); // t3M: number[]

Live code playground

Update: If T[] | [T] looks too weird, you can also use variadic tuple notation (TS 4.0):

callbackfn: (value: T, index: number, tuple: [...this]) => U

Live code playground

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.