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.

Mapped tuples types iterates over all properties

See original GitHub issue

TypeScript Version: 3.2.0-dev.20181019

Search Terms: mapped tuples reify

Code

type Foo = ['a', 'b'];
interface Bar
{
	a: string;
	b: number;
}

type Baz = { [K in keyof Foo]: Bar[Foo[K]]; }; // Expected Baz to be [string, number]

Expected behavior: Baz should be [string, number]

Actual behavior: Type ‘[“a”, “b”][K]’ cannot be used to index type ‘Bar’.

Playground Link: https://www.typescriptlang.org/play/index.html#src=type Foo %3D [‘a’%2C ‘b’]%3B interface Bar { a%3A string%3B b%3A number%3B } type Baz %3D { [K in keyof Foo]%3A Bar[Foo[K]]%3B }%3B %2F%2F Expected Baz to be [string%2C number] type WorkingBaz %3D { [K in Exclude<keyof Foo%2C keyof any[]>]%3A Foo[K] extends keyof Bar %3F Bar[Foo[K]] %3A never%3B } %26 { length%3A Foo[‘length’]%3B } %26 any[]%3B

Related Issues: https://github.com/Microsoft/TypeScript/issues/25947

Given the Mapped tuple types feature (#25947). I’d expect the code above to work cleanly.

However, I still need to do:

type WorkingBaz = { [K in Exclude<keyof Foo, keyof any[]>]: Foo[K] extends keyof Bar ? Bar[Foo[K]] : never; } & { length: Foo['length']; } & any[];

To have an equivalent type. As far as I understand, the “K” in a mapped type on a tuple should iterate only on numeric keys of this tuple. Therefore, Foo[K] should always be a valid key for Bar…

Issue Analytics

  • State:open
  • Created 5 years ago
  • Reactions:43
  • Comments:31 (7 by maintainers)

github_iconTop GitHub Comments

10reactions
weswighamcommented, Oct 19, 2018

This is because, despite mapped types not behaving as such, keyof ["some", "tuple"] still returns 0 | 1 | "length" | ... | "whatever" instead of 0 | 1.

9reactions
ksaldana1commented, Nov 23, 2018

@lemoinem You can get your current example to narrow correctly and avoid the behavior @weswigham mentioned with a couple of helper conditional types. Note: this comes with some not so great drawbacks… You lose all array prototype methods and properties, which for my current use case–messing with React hooks–that tradeoff isn’t the worst thing in the world.

export type ArrayKeys = keyof any[];
export type Indices<T> = Exclude<keyof T, ArrayKeys>;

type Foo = ['a', 'b'];

interface Bar {
  a: string;
  b: number;
}

type Baz = { [K in Indices<Foo>]: Bar[Foo[K]] }; // type is { "0": string, "1": number }

The way this type ends up formatting isn’t the greatest, but it ultimately maps to some of your desired outcomes. I am having issues around some constructs I thought would work, similar to @phiresky 's examples. I will get some better examples together and document those, but for now just wanted to provide a bit of a workaround.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Why are Typescript Mapped Tuple Types behaving differently ...
The issue here is that we only map to tuple and array types when we instantiate a generic homomorphic mapped type for a...
Read more >
TypeScript 3.1 Adds Mappable Tuple and Array Types - InfoQ
Nearly every JavaScript application needs to map over values in a list, which is a pattern that gets simplified with ES2015 via rest...
Read more >
Documentation - Mapped Types - TypeScript
Mapped types build on the syntax for index signatures, which are used to declare the types of properties which have not been declared...
Read more >
A Generic Mapper with Value Tuples and Generic Tests.
Mapping is the process of transferring data from a producer class to ... of type PropertyInfo that holds the metadata for every property...
Read more >
Using the Iterate Operator - TIBCO Software
Introduction · By default, Iterate emits one tuple for each element in the list. · By default, the emitted tuples contain all of...
Read more >

github_iconTop Related Medium Post

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