I am trying to type the accumulator in a JavaScript reducer
using JSDocs but cannot work out how to do this.
I've tried typing it inline at initialization but that didn't work. Any hints or ideas? Here's the sample code. It's plaining about param passed to arr.push():
/**
* @type {Array<String>}
*/
const arr = ['one', 'two', 'three'];
/**
* @type {Array<Array>}
*/
const result = arr.reduce((acc, item) => {
if(item.length % 3 === 0) {
// [ts] Argument of type '(string | number)[]' is not assignable to
// parameter of type 'never'.
acc.push([item, item.length]);
}
return acc;
}, []);
Here's the GitHub repo which has the tsconfig.json
file in the root of the project for the tsc settings:
And here's the file in that repo from which I took the code above: .js
I am trying to type the accumulator in a JavaScript reducer
using JSDocs but cannot work out how to do this.
I've tried typing it inline at initialization but that didn't work. Any hints or ideas? Here's the sample code. It's plaining about param passed to arr.push():
/**
* @type {Array<String>}
*/
const arr = ['one', 'two', 'three'];
/**
* @type {Array<Array>}
*/
const result = arr.reduce((acc, item) => {
if(item.length % 3 === 0) {
// [ts] Argument of type '(string | number)[]' is not assignable to
// parameter of type 'never'.
acc.push([item, item.length]);
}
return acc;
}, []);
Here's the GitHub repo which has the tsconfig.json
file in the root of the project for the tsc settings: https://github./guyellis/typescript-as-a-linter
And here's the file in that repo from which I took the code above: https://github./guyellis/typescript-as-a-linter/blob/master/lib/reducer.js
Share Improve this question edited Sep 4, 2018 at 0:51 Guy asked Sep 3, 2018 at 15:16 GuyGuy 67.3k101 gold badges265 silver badges331 bronze badges 3-
1
BTW why are you using
reduce
instead of what appear to be a job formap
?const result = arr.map(item => [item, item.length]);
. – ibrahim mahrir Commented Sep 3, 2018 at 15:27 -
@ibrahimmahrir - good question. It's a really bad example! I should have provided an example that produced a larger or smaller array instead of something that should use
map()
. – Guy Commented Sep 4, 2018 at 0:39 - 1 I edit the question to make the example a bit more realistic. – Guy Commented Sep 4, 2018 at 1:04
3 Answers
Reset to default 10The empty array you are passing as the initial state gets the type never[]
. See this thread for more background. To avoid that, you can put it in a constant and give the constant a type:
/**
* @type {Array<String>}
*/
const arr = ['one', 'two', 'three'];
/** @type {Array<[string, number]>} */
const init = [];
/**
* @type {Array<[string, number]>}
*/
const result = arr.reduce((acc, item) => {
acc.push([item, item.length]);
return acc;
}, init);
You can also use inline types, but there is a hard requirement that you put parenthesis around the initial value. This is a "cast" syntax for JSDoc:
https://www.typescriptlang/docs/handbook/jsdoc-supported-types.html#casts
const result = arr.reduce((acc, item) => {
acc.push([item, item.length]);
return acc;
}, /** @type {Array<[string, number]>} */ ([]));
// Note the parenthesis are required ^^^^
/**
* @param {Pose['parameterValues']} values
* @param {Pose['variants']} variants
*/
function getSrc (values, variants) {
return values.reduce(
/** @param {{[key: string]:Array<string>}} paths */
(paths, { camera, light }, index) => {
paths[light.name] = []
for (let c = camera.start; c < camera.end; c += camera.increment) {
paths[light.name].push(
variants[index].replace('light', light.value).replace('camera', String(c))
)
}
return paths
}, {})
}