51

let's say I have a block of code that I'd like to only be present (or run) in a staging environment. I've set an environment variable in that enivronment (say, ENV = 'staging'), is there a way for TypeScript to access that variable during compilation?

example:

if (Environment['ENV'] == 'staging') console.log('testing');

which would compile to (the redundant, but efffective) if ('staging' == 'staging') ... on the above environment?

3
  • If this is a node application you can easily access environment variables at runtime. Is it crucial that the environment is injected at compile time? Commented Nov 16, 2016 at 0:38
  • It depends on how your TS app is compiled. For example, if you're using Webpack to build the app, you can use DefinePlugin (webpack.github.io/docs/list-of-plugins.html#defineplugin) to inject the value of environment variables at compile time. Commented Nov 16, 2016 at 0:43
  • @Marty yeah it's a Flask application running Webassets (which lacks the features listed elsewhere in this question regarding Webpack's ability to inject) Commented Nov 16, 2016 at 20:07

4 Answers 4

30

No, this is not possible.

If your TypeScript file runs in Node, you can use process.env since it's a regular Node API - but in that case, the environment variable is accessed at runtime, by your compiled file, not at compile time by TypeScript.

If your TypeScript file runs in the browser, then there is no process.env, so you cannot even access it at runtime. You could use a tool like Webpack to replace references to process.env variables in the compiled file with their respective values at build time - but that still is not TypeScript's doing.

So unfortunately the answer is no: TypeScript cannot do this, and you'll have to use something else (like Webpack, or even just a search and replace) to inject environment variables into your script.

Sign up to request clarification or add additional context in comments.

Comments

7

is there a way for TypeScript to access that variable during compilation

Yup. Prefer using process.env that works as is in node and can be used with webpack using --define.

More

Example showing how to use it for build output toggles : https://basarat.gitbook.io/typescript/main-1/build-toggles

6 Comments

unfortunately it's not a node application
it doesn't need to be. Webpack works with web applications and that is what the link covers as well.
So the answer should be "No, the TypeScript transpiler cannot access environmental variables"?!?
@JackMiller no, no progress has been made since posting this.
@TylerSebastian can you expand upon what that progress is? (also you should mark one of the answers as the "solution" if it was able to solve your problem)
|
1

It works in node.

npm install dotenv --save

Create a file with .env. Type inside it Staging = "staging"

in your server/app call it:

require('dotenv').config();

in your code, you can use it like :

if (process.env.Staging = "staging") //true
{ 
 foo(); 
}

Comments

-8

Finally figured out how to do this, if you're willing to use Python and Flask. It's kind of hacky, but the best solution I've been able to find so far. If you implement the TypeScript side correctly, it will happen as soon as your application is started- even if not quite at compile time.

There's 3 parts to this:

  1. Get the environment variable information in Python
  2. Embed the data into your webpage
  3. Access that data from your JavaScript/TypeScript code

Step 1

Setup the Python dictionary for external use

Somewhere in your Flask code in either the __init__.py file, the routes.py file, or some other similarly accessible file, have the following setup:

api_port = os.environ.get("API_PORT", "8888")
api_proto = os.environ.get("API_PROTOCOL", "ws://")
port = int(os.environ.get("PORT", 80))
version = os.environ.get("VERSION", "6.9")
developer_buttons = os.environ.get("DEVELOPER", "False") == "True"
ENV = os.environ.get("ENV", 'staging')

@server.context_processor
def inject_data() -> dict:
    # .context_processor information: https://stackoverflow.com/a/43336023/8705841
    flask_data = {'api_port',
                  'api_proto',
                  'port',
                  'version',
                  'developer_buttons',
                  'ENV',
                  'etc'}
    # Create a dictionary from a list of variables: https://stackoverflow.com/a/9496018/8705841
    return {'flask_data': dict(((k, eval(k)) for k in flask_data))}

The @server part should match the name of your Flask app variable (instantiated with server = Flask(__name__)) and does not particularly matter (usually it's called app). The flask_data dict/list should have all the Python variables you want ported over to the front end, but with quotes around them- the eval part of the return will grab the Python variable that matches the input string k.

Step 2

Make the data available on the webpage

In your index.html page, inside the <head> tag (next to your other <script> tags, have this tag as well:

<head>
    <!-- a whole bunch of stuff -->
    
    <!-- get all the Flask variables from Python -> TypeScript -->
    <script id=flask_data type="text/json">{{ flask_data|tojson }}</script>
    
    <!-- possibly a whole bunch more stuff -->
</head>

Basically every single StackOverflow post even mentioning Flask has the above copy-pasted.

Step 3

Access the data from any of your JavaScript files

This is the part that no one else talked about- actually using your data from within your JavaScript (or TypeScript) code, regardless of your directory setup. It's a little hacky, but basically you access the HTML element that has your embedded data and then parse it for use in your program however you want. This is technically TypeScript code, but should work for both JavaScript and TypeScript (it took a ton of trial and error to finally get it to work on my TypeScript build).

foo() {
    const flask_data = JSON.parse((document.querySelector('#flask_data') as HTMLElement).textContent || "");
    this.version = flask_data.version
    const env = flask_data.ENV;
    console.log("Data: " + flask_data); // just for debugging, not actually necessary
    console.log("Environment: " + env);
    console.log("Running version '" + this.version + "'");
    
    if (env === "staging") {
        do_something();
    else {
        do_something_else();
        return input_from_python;
    }
}
// the rest of your program, using any part of the flask_data dictionary however you need
// .
// .
// .

3 Comments

The question is about Typescript, not Python (!!!)
Yes @BrunoMarotta but there isn't a way to do it via just TypeScript, so I included my solution that shows the server setup alongside the TypeScript client setup for future users.
I think you didn't read the question carefully. It is about accessing variables during compile time. So the right answer is still: No it is not possible.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.