question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Assume arity of tuples when declared as literal

See original GitHub issue

Search Terms

tuples, length, arity

Suggestion

Now that #17765 is out I’m curious about if we could change the arity of tuples declared as literals. This was proposed as part of #16896 but I thought it might be better to pull this part out to have a discussion about this part of that proposal.

With fixed length tuples TypeScript allows you to convert [number, number] to number[] but not the other way around (which is great).

const foo = [1, 2];
const bar = [1, 2] as [number, number];

const foo2: [number, number] = foo;
const bar2: number[] = bar;

If you declare a constant such as foo above it would be nice if it would be nice if it would have the length as part of its type, that is, if foo was assumed to be of type [number, number] not number[].

This would have potential issues with mutable arrays allowing you to call push and pop although this isn’t different to present and was discussed a bit in #6229.

const foo = [1, 2] as [number, number]; // After this proposal TypeScript would infer the type as `[number, number]` not `number[]`.
foo.push(3); // foo is of type `[number, number]` even though it now has 3 elements.
foo.splice(2); // And now it has 2 elements again.

Use Cases

When using a function such as fromPairs from lodash it requires that the type is a list of tuples. A simplified version is

function fromPairs<T>(values: [PropertyKey, T][]): { [key: string]: T } {
  return values.reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {});
}

If I do

const foo = fromPairs(Object.entries({ a: 1, b: 2 }));

it works because the type passed into fromPairs is [string, number][], but if I try to say map the values to double their value I get a compile error:

const bar = fromPairs(Object.entries({ a: 1, b: 2 }).map(([key, value]) => [key, value * 2]));

as the parameter is of type (string | number)[][]

This can be fixed by going

const bar = fromPairs(Object.entries({ a: 1, b: 2 }).map(([key, value]) => [key, value * 2] as [string, number]));

but this is cumbersome.

Checklist

My suggestion meets these guidelines:

  • This wouldn’t be a breaking change in existing TypeScript / JavaScript code
  • This wouldn’t change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn’t a runtime feature (e.g. new expression-level syntax)

Issue Analytics

  • State:open
  • Created 5 years ago
  • Reactions:4
  • Comments:13 (3 by maintainers)

github_iconTop GitHub Comments

4reactions
RyanCavanaughcommented, Aug 27, 2018

P.S. …add…a…flag? 😉

I WILL TURN THIS CAR AROUND

3reactions
mhegazycommented, May 23, 2018

We did consider this when we were first adding support for tuples, and thought it was too big of a breaking change to add… there are a few issues already open proposing new syntax to address this: https://github.com/Microsoft/TypeScript/issues/16656 and https://github.com/Microsoft/TypeScript/issues/10195.

having said that, i would like to bring this back to discussion. i gave it a try today, and there were not that many breaks in our Real World Code, which is frankly surprising to me… they fall into two categories:

var x = [1, 2];
x = array;  // Error array is not assignable to [number, number]
type A = { foo: string, baz: string[]} ;
var a = <A> { baz: ["baz"] };  // type assertion now fails
var c = [[1, 2]].concat([[3]]); // [[number]] is not assignable to [number,number] | ConcatArray<[number, number]>
Read more comments on GitHub >

github_iconTop Results From Across the Web

Minko Gechev Twitterren: "TypeScript tip: use `as const` after literals ...
TypeScript tip: use `as const` after literals to: ‣ Recursively set object properties to ... Assume arity of tuples when declared as literal...
Read more >
Essential .NET - C# 7.0: Tuples Explained | Microsoft Learn
ValueTuple that serves as a tuple factory with Create methods corresponding to each value tuple arity. The ease of using a tuple literal,...
Read more >
Arrays - Flow
Tuples are arrays, so they are declared like array literals ... The arity (i.e. length) of a tuple is strictly enforced, so that...
Read more >
Protocol Conformance for Tuples / Anonymous Structs - Pitches
Right now tuples cannot be used as literals to construct structs. Assume there is a function prettyPrintAsJson(data: Encodable) that you ...
Read more >
Chapter 8. Predicates - LogicBlox 4 Reference Manual
Tuples in a predicate must all have the same arity, or number of elements. This arity is also referred to as the arity...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found