如何正确为TypeScript泛型函数使用JSDoc?解决ts(80004)报错
Hey there, let's break down the best practices for using JSDoc with TypeScript generic functions, and fix that ts(80004) warning and post-quick-fix bug you're dealing with.
Core Best Practices
- Prioritize TypeScript's native type annotations: In a pure TS project, there's almost no need to use JSDoc for defining generics, parameter types, or return types. The TS type system is designed for this, and mixing JSDoc types with TS annotations often causes conflicts (like the warning you got).
- Use
@templatefor JSDoc generics (if you must): If you're working in a mixed JS/TS codebase and need JSDoc for generics, use the@templatetag instead of@typeto declare generic parameters. - Keep JSDoc focused on documentation, not types: Reserve JSDoc for explaining what the function does, not what types it uses—let TS handle the type enforcement.
Fixing Your Code
Your original JSDoc used @type <ReturnType> to declare the generic, which is incorrect syntax. Plus, you were duplicating type information between JSDoc and TS annotations, which triggered the ts(80004) warning. When you ran the quick fix, it likely messed up the generic association because it couldn't reconcile the conflicting type definitions.
Here's the cleaned-up, TS-native version (this is the recommended approach for pure TS projects):
/** * Executes promises in parallel by specified chunk size * Maintains the order of results matching the original promise array * @param arrayPromises Array of functions that return promises to execute * @param chunks Number of parallel promises to run at once */ const runPromisesInParallelbyChunks = async <ReturnType>( arrayPromises: Array<() => Promise<ReturnType>>, chunks: number ): Promise<ReturnType[]> => { const result: ReturnType[] = []; let counter = 0; const processChain = async (remainingPromises: Array<() => Promise<ReturnType>>): Promise<void> => { if (!remainingPromises.length) return; const currentIndex = counter++; const promiseResult = await remainingPromises.shift()!(); await delayExecution(100); // Assuming this is a defined utility function result[currentIndex] = promiseResult; return processChain(remainingPromises); }; const activeChains: Promise<void>[] = []; while (chunks-- > 0 && arrayPromises.length > 0) { activeChains.push(processChain(arrayPromises)); } await Promise.all(activeChains); return result; };
Key Fixes & Improvements:
- Removed redundant JSDoc type declarations: The JSDoc now only describes the function's behavior, not the types—TS handles that natively.
- Fixed the
chainfunction return type: Your originalchainfunction returnedPromise<ReturnType>, but the base case returned an empty promise (which doesn't matchReturnType). Changing it toPromise<void>makes the type safe. - Simplified variable logic: Got rid of the redundant
resuvariable—we can just returnresultdirectly after waiting for all chains to finish. - Renamed variables for clarity:
cnt→counter,shrinkArray→remainingPromisesto make the code easier to read.
If you really need to keep JSDoc type declarations (for a mixed codebase), here's the correct JSDoc syntax (note we remove the TS parameter types here to avoid conflicts):
/** * Executes promises in parallel by specified chunk size * Maintains the order of results matching the original promise array * @template ReturnType - Type of value returned by each promise * @param {Array<() => Promise<ReturnType>>} arrayPromises Array of functions that return promises to execute * @param {number} chunks Number of parallel promises to run at once * @returns {Promise<ReturnType[]>} Array of results in the order of the original promise array */ const runPromisesInParallelbyChunks = async <ReturnType>( arrayPromises, chunks ): Promise<ReturnType[]> => { // Same function body as above };
Final Note
In most TypeScript projects, sticking to native TS type annotations will save you from warnings and type conflicts. Use JSDoc to add context and explanations, not to replicate type information that TS can already infer or enforce.
内容的提问来源于stack exchange,提问作者Jerome

