6

Let's assume I have an input which adheres to a defined type:

interface Person {
    name: string;
    age: number;
}

Now, I want a function to accept an array of key-value pairs, e.g.:

function acceptsPersonProperties(tuple: Array<PersonTuple>) { ... }

// this should be fine:
acceptsPersonProperties([['name', 'Bob'], ['age', 42]]);

// this should give a compile-time error:
acceptsPersonProperties([['name', 2], ['age', 'Bob']]);

Of course, I can type this manually, e.g.:

type PersonTuple = ['name', string] | ['age', number];

But if type (e.g. Person) is a template variable, how can the tuple be expressed as a mapped type?

function acceptsPropertiesOfT<T>(tuple: Array<MappedTypeHere<T>>) { ... }

To avoid an X-Y-Problem, the real use case is this:

let request = api.get({
    url: 'folder/1/files',
    query: [
        ['fileid', 23],
        ['fileid', 47],
        ['fileid', 69]
    ]
});

which resolves to "/api/folder/1/files?fileid=23&fileid=47&fileid=69", but which I want to type, so it does not allow extra properties (file_id) and checks types (no string as fileid).

Leon Adler
  • 2,993
  • 1
  • 29
  • 42

1 Answers1

4

You can't do it with tuple types. The right side of the tuple will always get generalized to a union of all possible values in Person.

You can, however, make it work if you change your API slightly:

interface Person {
  name: string;
  age: number;
}

function acceptsPersonProperties(tuple: Partial<Person>[]) { }

// this should be fine:
acceptsPersonProperties([{ name: 'Bob' }, { age: 42 }]);

// this should give a compile-time error:
acceptsPersonProperties([{ name: 2 }, { age: 'Bob' }]);
bcherny
  • 3,072
  • 2
  • 27
  • 35
  • Thanks for your answer! I've updated my question to include the "real-world" scenario. It's sad that it is not (yet?) possible with tuples :/ The API is not mine, so changing it for TypeScript compliance seems ... hackish. – Leon Adler Apr 28 '17 at 06:47
  • I'm not sure I understand the question. Are you after something like this (which doesn't need mapped types) - https://gist.github.com/bcherny/d70434e5bb53bb88dda29f900d385bbf – bcherny Apr 30 '17 at 04:07