Summary
An async arrow function with type parameters gets them wrapped into its parameter list:
export const load = async <T>(key: string, fallback: T): Promise<T> => fallbackemits export declare const load: (<T>(key: string, fallback: T): Promise<T>) => Promise<unknown>;, which does not parse. A knip fixture (exports/basic/my-module.ts) comes out this way. tsc and the Zig port emit <T>(key: string, fallback: T) => Promise<T>.
Changes
The async branch of inferFunctionType now takes leading type parameters off the same way the branch for other arrows right below it does (findMatchingBracket on a leading <), and puts them in front of the signature.
Testing
New test/async-generic-arrow.test.ts, each case type-checked through a consumer with the existing runTsc helper. It covers an annotated return type, a constraint holding an arrow type with a block body, and a type parameter default. All three fail on main.
bun test (Zig library built with the pinned Zig, so its tests run too), typecheck, lint and zig build test pass. Over 4,192 files from vue-core, vue-router, pinia and knip (LF and CRLF), the only output that changes is the knip fixture, which now parses. Over 11,774 more from tailwindcss, stacks, eslint-plugin-vue and home, nothing changes.