Converting a Large Create React App Project from JavaScript to TypeScript
Posted on August 21, 2021
The TypeScript Addiction
I'm working on a large industrial react project, scaffolded by create-react-app
. The project was started in 2018, just before TypeScript really started becoming well known and used. Using TypeScript is nearly a must for me - so I took some time to convert all the JavaScript to TypeScript across 300+ files.
Here's how I did it.
Converting the Project to TypeScript... Incremental Method
Sure, there are (in my opinion somewhat convoluted) ways to convert your create react app project incrementally to TypeScript - but let's be honest, that's boring! I want ALL THE TYPESCRIPT! Ultimately, that linked example is more of a way to trick VS Code into liking both your JavaScript and TypeScript files. So again, in my opinion, it's not the best solution.
Converting the Project to TypeScript... Brute Force Method
My way, which may also not be the best solution, is a relatively easy way to convert your entire code base to TypeScript. It is a two step process coordinated by two shell scripts:
rename-to-js-and-jsx.sh
- Convert all .js and .jsx files to .ts and .tsx files respectively.prepend-ts-nocheck.sh
- Add //@ts-nocheck to the top of every file
It ain't pretty, but it gets the job done.
This method rapidly gets you to a fair starting point to being able to write anything new with TypeScript, and legacy code can be carefully and systematically updated to TypeScript as needed by removing the //@ts-nocheck
at the top of each file.
The only thing I struggled with was a global variable as a counter in the bash script. Unfortunately, because find
spawns a sub process, you can't use a variable. So I ended up using a sort of hack: just reading and writing on a temporary text file to keep track of the value.
Note also how I distinguish how to convert a .jsx (or .js) file to a .tsx
file: If the first like includes import React
. You may want to improve this yourself if react
is not always the top import in your JSX files, or if you are using import * from
or require
syntax.
The Scripts
Probably what you've been waiting for!
Note that these scripts will operate on all files within the src/
folder - which should be where all your source code is in a project that was scaffolded by create-react-app
.
⚠️ Warning: these scripts use mv
and quite literally replace the .js
or .jsx
files with their TypeScript counterparts. Proceed at your own risk, use git or backup your work, and read through these scripts. You have been warned! ⚠️
Here's the first step script rename-to-js-and-jsx.sh
:
#!/bin/bash
rename() {
extension="${1##*.}"
contents=$(cat $1)
if [[ $contents == *"import React"* ]]
then
mv "$1" "${1%.$extension}.tsx"
echo "Renamed $1 to ${1%.$extension}.tsx"
tsCount=$(cat tsCount.temp)
((tsCount++))
echo $tsCount > tsCount.temp
else
mv "$1" "${1%.$extension}.ts"
echo "Renamed $1 to ${1%.$extension}.ts"
tsxCount=$(cat tsxCount.temp)
((tsxCount++))
echo $tsxCount > tsxCount.temp
fi
}
runFindCommand() {
echo "0" > tsCount.temp
echo "0" > tsxCount.temp
find src \( -name "*.js" -o -name "*.jsx" \) -exec bash -c 'rename "$@"' bash {} \;
tsCount=$(cat tsCount.temp)
tsxCount=$(cat tsxCount.temp)
totalFiles=$((tsCount + tsxCount))
echo "Done. Renamed $totalFiles files:"
echo "- $tsCount files from .js to .ts"
echo "- $tsxCount files from .js (or .jsx) to .tsx"
rm tsCount.temp
rm tsxCount.temp
}
export -f rename
runFindCommand
and the second step script, prepend-ts-nocheck.sh
:
#!/bin/bash
prependNoCheck() {
extension="${1##*.}"
contents=$(cat $1)
echo "Prepending $1 with '// @ts-nocheck'"
echo '// @ts-nocheck' | cat - $1 > temp && mv temp $1
count=$(cat count.temp)
((count++))
echo $count > count.temp
}
runFindCommand() {
echo "0" > count.temp
find src \( -name "*.ts" -o -name "*.tsx" \) -exec bash -c 'prependNoCheck "$@"' bash {} \;
count=$(cat count.temp)
echo "Done. Prepended $count files."
rm count.temp
}
export -f prependNoCheck
runFindCommand
Thanks!
Thanks for reading and I hope you enjoyed. Remember:
⚠️ Use these scripts at your own risk! ⚠️
But that's what we have git for! 😉
Cheers! 🍻
-Chris