Skip to content

Bug: TypeScript and LintOptions interface: filterCodeBlock should not be typed as boolean #19836

@khawkins

Description

@khawkins

Environment

Node version: 22.15.1
npm version: 10.9.2
Local ESLint version: 9.28.0
Global ESLint version: N/A
Operating System: macOS Sequoia 15.5

What parser are you using?

Default (Espree)

What did you do?

In my TypeScript (5.7.3) project, I'm trying to programmatically call Linter.verifyAndFix(code, config, options), specifying the filterCodeBlock property of options since my plugin takes both JS and HTML files.

The LintOptions interface in lib/types/index.d.ts specifies filterCodeBlock's type as boolean | undefined. filterCodeBlock should be a function type that returns a boolean.

And indeed, if you try to run Linter.verifyAndFix() with filterCodeBlock set to e.g. true (as its specified type would suggest), you get the following error when the linter tries to run that (non-)function:

TypeError: filterCodeBlock is not a function

What did you expect to happen?

In TypeScript I expect to be able to specify filterCodeBlock as a function type that returns a boolean, not as a boolean property itself. I can get around this by creating my function type, then casting it to boolean, a la:

{ filename: 'myFile.html', filterCodeBlock: myFilterCodeBlock as unknown as boolean }

That makes the code function. But that's clearly not the intent of the type interface.

What actually happened?

Having to set filterCodeBlock as a boolean makes Linter.verifyAndFix() throw a TypeError at runtime.

Link to Minimal Reproducible Example

https://eslint.org/play/#eyJ0ZXh0IjoiaW1wb3J0IHsgTGludGVyIH0gZnJvbSAnZXNsaW50Jztcbi8vIGNvbnN0IGpzVG9BbmFseXplID0gJ3ZvaWQgMDsnO1xuY29uc3QgaHRtbFRvQW5hbHl6ZSA9ICc8aHRtbD48Ym9keT48cD5IZWxsbyB3b3JsZDwvcD48L2JvZHk+PC9odG1sPidcbmNvbnN0IHByb2Nlc3NvciA9IHtcbiAgcHJlcHJvY2VzczogKHRleHQsIGZpbGVuYW1lKSA9PiB7XG4gICAgaWYgKGZpbGVuYW1lLmVuZHNXaXRoKCcuanMnKSkge1xuICAgICAgcmV0dXJuIFt7IHRleHQsIGZpbGVuYW1lIH1dO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gW3sgdGV4dDogJycsIGZpbGVuYW1lIH1dO1xuICAgIH1cbiAgfSxcbiAgcG9zdHByb2Nlc3M6IChtZXNzYWdlcykgPT4ge1xuICAgIHJldHVybiBtZXNzYWdlcy5mbGF0KCk7XG4gIH1cbn1cbmNvbnN0IGxpbnRlciA9IG5ldyBMaW50ZXIoKTtcbi8vIGNvbnN0IGZpbHRlckNvZGVCbG9ja0dvb2QgPSAoYmxvY2tGaWxlbmFtZSkgPT4ge1xuLy8gICByZXR1cm4gYmxvY2tGaWxlbmFtZS5lbmRzV2l0aChcIi5qc1wiKSB8fCBibG9ja0ZpbGVuYW1lLmVuZHNXaXRoKFwiLmh0bWxcIik7XG4vLyB9O1xuY29uc3QgZmlsdGVyQ29kZUJsb2NrQmFkID0gdHJ1ZTtcbmxpbnRlci52ZXJpZnlBbmRGaXgoaHRtbFRvQW5hbHl6ZSwge1xuICBmaWxlczogW1wiKi5qc1wiLCBcIioqLyouanNcIiwgXCIqLmh0bWxcIiwgXCIqKi8qLmh0bWxcIl0sXG4gIHByb2Nlc3Nvcixcbn0sIHtcbiAgICBmaWxlbmFtZTogJ215SHRtbC5odG1sJyxcbiAgICBmaWx0ZXJDb2RlQmxvY2s6IGZpbHRlckNvZGVCbG9ja0JhZCxcbiAgfVxuKTsiLCJvcHRpb25zIjp7InJ1bGVzIjp7ImNvbnN0cnVjdG9yLXN1cGVyIjpbImVycm9yIl0sImZvci1kaXJlY3Rpb24iOlsiZXJyb3IiXSwiZ2V0dGVyLXJldHVybiI6WyJlcnJvciJdLCJuby1hc3luYy1wcm9taXNlLWV4ZWN1dG9yIjpbImVycm9yIl0sIm5vLWNhc2UtZGVjbGFyYXRpb25zIjpbImVycm9yIl0sIm5vLWNsYXNzLWFzc2lnbiI6WyJlcnJvciJdLCJuby1jb21wYXJlLW5lZy16ZXJvIjpbImVycm9yIl0sIm5vLWNvbmQtYXNzaWduIjpbImVycm9yIl0sIm5vLWNvbnN0LWFzc2lnbiI6WyJlcnJvciJdLCJuby1jb25zdGFudC1iaW5hcnktZXhwcmVzc2lvbiI6WyJlcnJvciJdLCJuby1jb25zdGFudC1jb25kaXRpb24iOlsiZXJyb3IiXSwibm8tY29udHJvbC1yZWdleCI6WyJlcnJvciJdLCJuby1kZWJ1Z2dlciI6WyJlcnJvciJdLCJuby1kZWxldGUtdmFyIjpbImVycm9yIl0sIm5vLWR1cGUtYXJncyI6WyJlcnJvciJdLCJuby1kdXBlLWNsYXNzLW1lbWJlcnMiOlsiZXJyb3IiXSwibm8tZHVwZS1lbHNlLWlmIjpbImVycm9yIl0sIm5vLWR1cGUta2V5cyI6WyJlcnJvciJdLCJuby1kdXBsaWNhdGUtY2FzZSI6WyJlcnJvciJdLCJuby1lbXB0eSI6WyJlcnJvciJdLCJuby1lbXB0eS1jaGFyYWN0ZXItY2xhc3MiOlsiZXJyb3IiXSwibm8tZW1wdHktcGF0dGVybiI6WyJlcnJvciJdLCJuby1lbXB0eS1zdGF0aWMtYmxvY2siOlsiZXJyb3IiXSwibm8tZXgtYXNzaWduIjpbImVycm9yIl0sIm5vLWV4dHJhLWJvb2xlYW4tY2FzdCI6WyJlcnJvciJdLCJuby1mYWxsdGhyb3VnaCI6WyJlcnJvciJdLCJuby1mdW5jLWFzc2lnbiI6WyJlcnJvciJdLCJuby1nbG9iYWwtYXNzaWduIjpbImVycm9yIl0sIm5vLWltcG9ydC1hc3NpZ24iOlsiZXJyb3IiXSwibm8taW52YWxpZC1yZWdleHAiOlsiZXJyb3IiXSwibm8taXJyZWd1bGFyLXdoaXRlc3BhY2UiOlsiZXJyb3IiXSwibm8tbG9zcy1vZi1wcmVjaXNpb24iOlsiZXJyb3IiXSwibm8tbWlzbGVhZGluZy1jaGFyYWN0ZXItY2xhc3MiOlsiZXJyb3IiXSwibm8tbmV3LW5hdGl2ZS1ub25jb25zdHJ1Y3RvciI6WyJlcnJvciJdLCJuby1ub25vY3RhbC1kZWNpbWFsLWVzY2FwZSI6WyJlcnJvciJdLCJuby1vYmotY2FsbHMiOlsiZXJyb3IiXSwibm8tb2N0YWwiOlsiZXJyb3IiXSwibm8tcHJvdG90eXBlLWJ1aWx0aW5zIjpbImVycm9yIl0sIm5vLXJlZGVjbGFyZSI6WyJlcnJvciJdLCJuby1yZWdleC1zcGFjZXMiOlsiZXJyb3IiXSwibm8tc2VsZi1hc3NpZ24iOlsiZXJyb3IiXSwibm8tc2V0dGVyLXJldHVybiI6WyJlcnJvciJdLCJuby1zaGFkb3ctcmVzdHJpY3RlZC1uYW1lcyI6WyJlcnJvciJdLCJuby1zcGFyc2UtYXJyYXlzIjpbImVycm9yIl0sIm5vLXRoaXMtYmVmb3JlLXN1cGVyIjpbImVycm9yIl0sIm5vLXVuZGVmIjpbImVycm9yIl0sIm5vLXVuZXhwZWN0ZWQtbXVsdGlsaW5lIjpbImVycm9yIl0sIm5vLXVucmVhY2hhYmxlIjpbImVycm9yIl0sIm5vLXVuc2FmZS1maW5hbGx5IjpbImVycm9yIl0sIm5vLXVuc2FmZS1uZWdhdGlvbiI6WyJlcnJvciJdLCJuby11bnNhZmUtb3B0aW9uYWwtY2hhaW5pbmciOlsiZXJyb3IiXSwibm8tdW51c2VkLWxhYmVscyI6WyJlcnJvciJdLCJuby11bnVzZWQtcHJpdmF0ZS1jbGFzcy1tZW1iZXJzIjpbImVycm9yIl0sIm5vLXVudXNlZC12YXJzIjpbImVycm9yIl0sIm5vLXVzZWxlc3MtYmFja3JlZmVyZW5jZSI6WyJlcnJvciJdLCJuby11c2VsZXNzLWNhdGNoIjpbImVycm9yIl0sIm5vLXVzZWxlc3MtZXNjYXBlIjpbImVycm9yIl0sIm5vLXdpdGgiOlsiZXJyb3IiXSwicmVxdWlyZS15aWVsZCI6WyJlcnJvciJdLCJ1c2UtaXNuYW4iOlsiZXJyb3IiXSwidmFsaWQtdHlwZW9mIjpbImVycm9yIl19LCJsYW5ndWFnZU9wdGlvbnMiOnsicGFyc2VyT3B0aW9ucyI6eyJlY21hRmVhdHVyZXMiOnt9fX19fQ==

Participation

  • I am willing to submit a pull request for this issue.

Additional comments

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    acceptedThere is consensus among the team that this change meets the criteria for inclusionbugESLint is working incorrectlyrepro:yesIssues with a reproducible exampletypesRelated to TypeScript types

    Type

    No type

    Projects

    Status

    Complete

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions