Reputation: 111
I use @ts-check
and ts linter on an ecmascript projet (I cannot use typescript but want its formalism).
All is going well except for one thing: I want to use JSDoc generics declaration so that return type is tied-to/inferred-from a parameter type:
/**
* @template V - Type de valeurs de la map.
* @param {Map<string, V>} map
* @returns {Object.<string, V>}
*/
function objectifyMap(map) {
/** @type {Object.<string,V>} */
const result = {};
map.forEach((value, key) => { result[key] = value; });
return result;
}
/**
* @template V
* @param {Object.<string, V>} object
* @returns {Map<string, V>}
*/
function mappifyObject(object) {
/** @type {Map<string,V>} */
const result = new Map();
Object.entries(object).forEach(([key, value]) => { result.set(key, value); });
return result;
}
/** @type {Object.<string, string>} */
const obj = {};
/** @type {Map<string, string>} */
let map;
map = mappifyObject(obj);
But on the last line, ts linter throws an error on obj
parameter:
Argument of type '{ [x: string]: string; }' is not assignable to parameter of type '{ [x: string]: V; }'.
Index signatures are incompatible.
Type 'string' is not assignable to type 'V'.
'V' could be instantiated with an arbitrary type which could be unrelated to 'string'.ts(2345)
I guess ts linter is expecting map = mappifyObject<string>(obj);
but as I'm only using @ts-check
and not the typescript transpiler, I cannot do that.
Does anyone knows how to circumvent that?
Upvotes: 3
Views: 2600
Reputation: 1140
I'm not familiar with the Object.<K, V>
type syntax you're using. In actual TypeScript, the typing would be either {[x: string]: V}
or Record<string, V>
. Either one of those typings works for me:
/**
* @template V
* @param {{[x: string]: V}} object
* @returns {Map<string, V>}
*/
function mappifyObject(object) {
/** @type {Map<string,V>} */
const result = new Map();
Object.entries(object).forEach(([key, value]) => { result.set(key, value); });
return result;
}
/** @type {{[x: string]: string}} */
const obj = {};
/** @type {Map<string, string>} */
let map;
map = mappifyObject(obj);
or
/**
* @template V
* @param {Record<string, V>} object
* @returns {Map<string, V>}
*/
function mappifyObject(object) {
/** @type {Map<string,V>} */
const result = new Map();
Object.entries(object).forEach(([key, value]) => { result.set(key, value); });
return result;
}
/** @type {Record<string, string>} */
const obj = {};
/** @type {Map<string, string>} */
let map;
map = mappifyObject(obj);
Both work without errors.
Upvotes: 1