4

I'm trying to create a Map object from a string,function dictionnary.

const entityTagDictionnary = [
  ['GRAPH_ADD_PROPERTY_SUBTYPE', (entity) => {
    console.log('addSubtype called!');
    return entity;
  }],
  ['GRAPH_IGNORE_PROPERTY_SENTENCE', (entity) => {
    console.log('ignore property called!');
    return entity;
  }],
  ['GRAPH_FORMAT_DATES', (entity) => {
    console.log('formatDates called!');
    return entity;
  }],
];

const entityMap : Map<string, Function> = new Map(entityTagDictionnary);

I've got the following error:

Argument of type '(string | ((entity: any) => any))[][]' isn't matching the argument 'Iterable<[string, Function]>'.

Am I doing anything wrong?

0

2 Answers 2

5

The problem is that the constructor to map takes an array of tuples and infers the type based on the tuple type. The signature for this constructor is :

new <K, V>(entries?: ReadonlyArray<[K, V]>): Map<K, V>;

The problem with your array is that is is not an array of tuples, it's an array of arrays, an item of the inner array being string | ((e: any) => any). Typescript does not infer tuple types based on array literals unless it is required to do so. The simple solution is to put the array literal in the constructor argument:

const entityMap: Map<string, Function> = new Map([
    ['GRAPH_ADD_PROPERTY_SUBTYPE', (entity: any) => {
        console.log('addSubtype called!');
        return entity;
    }],
    ['GRAPH_IGNORE_PROPERTY_SENTENCE', (entity: any) => {
        console.log('ignore property called!');
        return entity;
    }],
    ['GRAPH_FORMAT_DATES', (entity: any) => {
        console.log('formatDates called!');
        return entity;
    }],
]);

Or use an explicit type annotation:

const entityTagDictionnary: Array<[string, (e: any)=> any]> = [...]

Or you can use a tuple helper function to force typescript to infer tuple types, as described here

function tupleArray<T1, T2, T3>(arr:[T1, T2, T3][]) : typeof arr 
function tupleArray<T1, T2>(arr:[T1, T2][]) : typeof arr 
function tupleArray<T1>(arr:[T1][]) : typeof arr 
function tupleArray(arr:any[]) : any[]{
    return arr;
}
const entityTagDictionnary = tupleArray([
]);
Sign up to request clarification or add additional context in comments.

Comments

3

You could try the following workaround instead

const entityTagDictionnary: {[key:string]:Function} = {
   GRAPH_ADD_PROPERTY_SUBTYPE: (entity)=>{
    console.log('addSubtype called!');
    return entity;
   },
   ...
}

Then you don't need to use the new Map() call at all, and you can test it by running entityTagDictionnary['GRAPH_ADD_PROPERTY_SUBTYPE']('my entity');

2 Comments

A reasonable workaround for common situations, but there are differences between Map and using an object: stackoverflow.com/questions/18541940/…
Thank you for your comment and the link to the difference between Map and javascript object.

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.