Take the following Typescript arrow function:
/**
* Returns a probably unique component name.
*
* @param baseName a suggested name to make unique.
* @returns a probably unique name.
*/
export const getUniqueComponentName = (
baseName
): string => {
return baseName + Math.round(Math.random() * 10000000)
}
When Typescript is configured in tsconfig.json
as such:
"noImplicitAny": true,
This correctly results in a compilation error:
[ts] Parameter 'baseName' implicitly has an 'any' type.
Visual Studio Code is also smart enough to inform you about this issue during development.
My goal is to create a precommit git hook that prevents such errors from ending up in version control. I tried to do this with tslint
, husky
and lint-staged
using this npm script
:
"lint": "tslint --project tsconfig.json --config tslint.json"
However, this does not result in the compilation error showing up by tslint. It is silently ignored.
I then tried to add a rule in tslint.json:
"typedef": [
true,
"arrow-parameter"
]
While this did make tslint complain, it also started to complain in anonymous arrow functions where the tsc
compiler does not complain. In these arrow functions it should not be necessary to add types because the types were already set previously in the parent scope (they are inferred).
So basically, I would like for tslint to behave the same as tsc in this case. Anytime there is an error that would cause compilation to fail (such as the above arrow function), I would like to prevent the commit, but without actually compiling to Javascript. Is this possible?
ESLint is a JavaScript linter that you can use to lint either TypeScript or JavaScript code. In this post, we'll walk through how to set up linting in your project.
ESlint doesn't check for TypeScript errors, so if you want to check for TypeScript errors in your pre commit hook, you'll need to run the tsc --noEmit command in addition to the ESLint command.
Linters have been around for ages - it all started back in 1978 apparently - but has now become a mainstay of modern JavaScript and TypeScript programming. Writing code without a linter is like writing an essay without using spell checker!
The TypeScript compiler compiles these files and outputs the JavaScript with . js extension by keeping the same file name as the individual input file. The TypeScript compiler also preserves the original file path, hence the . js output file will be generated where the input file was in the directory structure.
I think your best bet is to run tsc --noEmit -p .
and filter the output for errors in the modified files. For example, I saved the following script to tsc-some-files
:
#!/bin/bash
declare -A include_files
for f in "$@"; do
include_files["${f#$PWD/}"]=1
done
node_modules/.bin/tsc --noEmit -p . | (
status=0
show_continuation=false
while IFS='' read -r line; do
case "$line" in
(' '*)
if $show_continuation; then
echo "$line" >&2
fi
;;
(*)
file="${line%%(*}"
if [ -n "${include_files["$file"]}" ]; then
show_continuation=true
echo "$line" >&2
status=1
else
show_continuation=false
fi
;;
esac
done
exit $status
)
and set ./tsc-some-files
as my lint-staged
command, and it seemed to work. (Writing this in a programming language other than bash, if desired, is left as an exercise for the reader.)
Keep in mind though that editing one file can introduce an error in another file (e.g., if you changed the type of something that the other file is using), so I'd urge you to get your project clean of TypeScript errors ASAP by whatever hacks necessary (as long as you mark them so you can search for them later) and then set your hook to require no errors in the whole project. In fact, with respect to noImplicitAny
in particular, when I migrated a JavaScript project to TypeScript several years ago, I wrote a script that inserted an explicit any
everywhere there was an implicit any
error, then I fixed the explicit any
s at my leisure. I can share the script if you're interested.
I don't have enough reputation to add this as a comment, but anyone that is getting an error similar to
./scripts/ts-staged-files.sh: line 4:
src/ui/Components/Select/Select.tsx: division by 0
(error token is "/Components/Select/Select.tsx")
I made this small modification to Matt McCutchen's answer to fix it.
#!/bin/bash
include_files=()
for f in "$@"; do
include_files+=("${f#$PWD/}")
done
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With