DEV Community

Vincent
Vincent

Posted on

Sharing Variables Across TypeScript and Bash Scripts

Problem

While working on a project, I came across an interesting issue. Multiple TypeScript and bash scripts needed to read from or write to a shared file. Thus, the scripts needed the file path (directly or indirectly). The question is: if the file location changes, how should I structure the code such that only one file needs to be updated (and thus reduce the risk of missing updates in various scripts)?

Attempt 1: Share a utils.ts file for Typescript files

The Typescript scripts could import the file path in a utils.ts and use a getSharedFilePath function e.g.

import { getSharedFilePath } from "utils";
const SHARED_PATH = getSharedFilePath();
Enter fullscreen mode Exit fullscreen mode

BUT! What about the bash scripts? They still hardcoded the path e.g.

SHARED_PATH="path/to/shared/file.json";
Enter fullscreen mode Exit fullscreen mode

Pros:

  • ✅ DRY for Typescript files (but not for bash scripts)

Cons:

  • ❌ Violates DRY principle. Changing the file location means updating the utils.ts and each bash script.
  • ⚠️ High risk of inconsistency or human error.

Attempt 2: Pass Full Path as Env Var

Instead of setting the path in each bash script, set it as an env var like SHARED_PATH.

jobs:
  deploy:
    env:
      SHARED_PATH: path/to/shared/file.json
    steps:
      - run: npx hardhat run scripts/deploy.ts
Enter fullscreen mode Exit fullscreen mode

Then in your TypeScript:

const { SHARED_PATH } = process.env;
Enter fullscreen mode Exit fullscreen mode

And in your bash scripts, just call it e.g.:

set -u # throw error if script references an undefined variable e.g. SHARED_PATH
echo $SHARED_PATH
Enter fullscreen mode Exit fullscreen mode

Pros:

  • ✅ DRY: Scripts are isolated from changes to the file path value i.e. the file structure and file name can change without requiring script updates.
  • ✅ Keeps configurable data at high levels: env vars
  • ✅ Consistent, uniform mechanism for both TypeScript and bash scripts to access the file path

Cons:

Here’s your list with fitting emojis prepended:

  • ⚠️ You lose path.join safety in TypeScript. That said, one could argue that environment variables should know the correct delimiter since they ought to be tailored to the environment.
  • ♻️ The env var either:

    • 🔁 Must be duplicated in every job that needs it, or
    • 🧪 Set at the workflow level, potentially polluting jobs that don’t use it, or
    • 🧩 Require a composite action to centralize, which adds complexity. At this point, would it be over-engineered?
  • 🔧 Dependency on env var and need for error handling to check that it's set correctly

Another option: Pass in the path as a parameter

While I didn't implement this, I could also have used hardhat tasks instead of scripts.

Pros:

  • ✅ DRY: within scripts (but not the interface calling the script)
  • ✅ Scripts are isolated from changes to the file path value

Cons:

  • 🚫 Opposes the principle of minimising function arguments
  • ⚙️ Hardhat tasks require more setup than hardhat scripts
  • 🔁 The parameters must be passed in every time the hardhat task or bash script is called

Conclusion

Using a shared Typescript utils file is insufficient. It only solves the problem for a subset of your codebase (TypeScript) and introduces inconsistency. Passing in the path as a parameter keeps code within scripts DRY, but requires adding an argument to the interface of every script that needs the path.

The solution I chose was to centralise the file path as a single env var. This provides the cleanest interface for all scripts — especially when dealing with both TypeScript and bash. It decouples the file path from script internals, which is valuable when the directory structure or file name may change.

Have a different strategy to manage shared variables across different languages? Share your knowledge or suggest improvements in the comments.

Top comments (0)