How to make a shell executable node file using Typ

2020-05-25 07:55发布

Normally in node files I just put

#!/usr/bin/env node 

at the top and make it executable to create a file that can be run from a bash terminal. However if I do that in a Typescript file, the compiler says "error TS1001: Unexpected character "#"" and refuses to compile it. So how can I make a shell executable node file with Typescript?

5条回答
劳资没心,怎么记你
2楼-- · 2020-05-25 08:11

I don't have enough reputation points to post a comment, but I'd just thought it'd be good for everyone to know that I opened a new issue on GitHub since that's what the Typescript devs are using to track things like this: https://github.com/Microsoft/TypeScript/issues/2749 .

查看更多
Lonely孤独者°
3楼-- · 2020-05-25 08:22

If you have TypeScript and ts-node installed globally:

npm install typescript ts-node -g

You can now easily do this with:

#!/usr/bin/env ts-node

console.log('Hello world')
查看更多
我只想做你的唯一
4楼-- · 2020-05-25 08:23

You were right to report the bug to Microsoft, and they were wrong to close it as wontfix.

Until it is fixed, here's a workaround. Paste the following into a text file and save it as shebangify:

#!/usr/bin/env node
var fs = require('fs');
var path = process.argv[2];
var data = "#!/usr/bin/env node\n\n";
data += fs.readFileSync(path);
fs.writeFileSync(path, data);

(N.B. To keep this answer concise, the code above doesn't have any error-checking or other refinements, so use at your own risk or use this instead. Also, see this SO question for more info about prepending to files.)

Make the file executable with by using a terminal to navigate to the file's directory and executing:

$ chmod +x shebangify

Once you have created a Typescript program (e.g. called myscript.ts) that you wish to compile and turn into a shell script (e.g. called myscript), do so by executing a sequence along these lines in your terminal:

$ tsc --out myscript myscript.ts ; ./shebangify myscript ; chmod +x myscript
查看更多
ら.Afraid
5楼-- · 2020-05-25 08:27

I've never been able to get ts-node to work, so I finally made my own way to write shell scripts in TypeScript. If there were a package manager for Bash I would make a package, but there isn't, so I just put this script in my path as ts-exec:

#!/usr/bin/env bash

file_to_run="$1"
basename=`basename "$1"`
tmp_prefix=`basename "$BASH_SOURCE"`

TMPDIR=`mktemp -d -t "$tmp_prefix-XXXXXXXXXX"`
pushd "$TMPDIR" > /dev/null

cp "$1" "$basename.ts"
tsc "$basename"
node "$basename.js"

popd > /dev/null
rm -rf "$TMPDIR"

And now I can do things like this:

#!/usr/bin/env ts-exec

let greeting: string = "Hello World!";

console.log( greeting );

And it works.

Of course, it does have some limitations

  • It's only suitable for scripts that are confined to a single file
  • It doesn't do any error checking
  • It has implicit dependencies
  • It doesn't have an installer

... so basically it's for bash nerds who want to use TypeScript for small scripts that would be a pain to write as Bash scripts. I'm still baffled that ts-node doesn't cover this case, and I'd rather not have to futz with temp files that might get left behind and waste space if there's an error, but so far this covers my use-case. (Besides, I've got that cronjob that deletes everything in ~/tmp that's more than 31622400 seconds old every night, so stray temp files can't eat my whole system.)

查看更多
Emotional °昔
6楼-- · 2020-05-25 08:28

See https://github.com/Microsoft/TypeScript/blob/master/bin/tsc for an example. Basically have a dummy file without the .js extension and just require the actual .js file.

E.g. In file named tsc:

#!/usr/bin/env node
require('./tsc.js')
查看更多
登录 后发表回答