The return value is not used, at all, despite what the function's type signature would have you believe. Instead, you're expected to assign the excerpt field to its first argument like so:
function firstFourLines(input: UnspecifiedObject, options: GrayMatterOption): void {
input.excerpt = input.content.split('\n').slice(0, 4).join(' ');
}
const { data } = graymatter(file, { excerpt: firstFourLines })
This is extremely easy to miss, and had me banging my head against the wall for hours. Hopefully this will help somebody with the foresight to check the GitHub issues.