[question] Is it possible to create a index.ts for both lua and js? · Issue #1681 · TypeScriptToLua/TypeScriptToLua · GitHub
Skip to content

[question] Is it possible to create a index.ts for both lua and js? #1681

Open

Description

@Freed-Wu

Expected behaviour

export async function f(this: void, filename: string) {
  let text;
  if (io !== undefined) {
    const f = io.open(filename)[0];
    if (f) {
      text = f.read("*a");
      f.close();
    }
  } else {
    const fs = require('fs');
    text = String(fs.readSync())
  }
  return `file is ${text}!`
}

Then run tstl to get lua and tsc to get js.

Actual behaviour

    "types": ["lua-types/5.1", "@types/node"],

Seems to be a conflict.

Activity

  1. Zamiell commented on Jan 30, 2026

    @Zamiell
    Contributor

    Can you try using 2 different "tsconfig.json" files? Name them "tsconfig.js.json" and "tsconfig.lua.json", and then point tsc at the former and point tstl at the latter.

  2. Cheatoid commented on Jan 31, 2026

    @Cheatoid
    Contributor

    I've run into similar issue recently, in my case I wanted to have 3 separate tsconfig in the same directory, with one being the "common base" and the other two being server/client separation. I tried running tstl with -p, but it seems tstl doesn't respect "extends" property in tsconfig for some reason.
    Is this just me, or is this supposed to work? Nevermind, it seems to be working now (lol)

    AI says:

    Example TypeScriptToLua project with three tsconfig files in the same directory:

    • tsconfig.base.json: shared config
    • tsconfig.client.json: client‑side config
    • tsconfig.server.json: server‑side config

    Each of the client/server configs extends the base config.

    This is a very common setup for full-stack TypeScriptToLua monorepos or unified projects.


    📁 Project Structure

    my-tstl-project/
    │
    ├── src/
    │   ├── client/
    │   │   └── main.ts
    │   ├── server/
    │   │   └── main.ts
    │   └── shared/
    │       └── utils.ts
    │
    ├── tsconfig.base.json
    ├── tsconfig.client.json
    ├── tsconfig.server.json
    └── package.json
    

    🧩 1. Base Config - tsconfig.base.json

    This contains all shared TSTL settings.

    {
        "compilerOptions": {
            "strict": true,
            "types": []
        },
        "tstl": {
            "luaTarget": "5.4"
        }
    }

    Notes:

    • tstl block contains TSTL‑specific options
    • No module or target as TSTL ignores those

    🖥️ 2. Client Config - tsconfig.client.json

    Client build extending the base config.

    {
        "extends": "./tsconfig.base.json",
        "compilerOptions": {
            "outDir": "./dist/client"
        },
        "include": [
            "src/client/**/*",
            "src/shared/**/*"
        ],
        "tstl": {
            "luaTarget": "5.4"
        }
    }

    🖧 3. Server Config - tsconfig.server.json

    Server build extending the base config.

    {
        "extends": "./tsconfig.base.json",
        "compilerOptions": {
            "outDir": "./dist/server"
        },
        "include": [
            "src/server/**/*",
            "src/shared/**/*"
        ],
        "tstl": {
            "luaTarget": "5.4"
        }
    }

    🧪 Example Source Files

    src/shared/utils.ts

    export function greet(name: string) {
        return "Hello, " + name + "!";
    }

    src/client/main.ts

    import { greet } from "../shared/utils";
    
    console.log(greet("Client"));

    src/server/main.ts

    import { greet } from "../shared/utils";
    
    console.log(greet("Server"));

    📦 package.json Example

    {
      "name": "multi-config-tstl-example",
      "private": true,
      "scripts": {
        "build:client": "npx tstl -p tsconfig.client.json",
        "build:server": "npx tstl -p tsconfig.server.json",
        "build": "npm run build:client && npm run build:server"
      },
      "devDependencies": {
        "typescript-to-lua": "^1.33.2",
        "typescript": "^5.9.3"
      }
    }

    🏁 Running the Build

    npm run build
    

    Produces:

    dist/
    ├── client/
    │   └── main.lua
    └── server/
        └── main.lua
    
  3. Freed-Wu commented on Jan 31, 2026

    @Freed-Wu
    Author

    Can you try using 2 different "tsconfig.json"

    error TSTL: Could not resolve lua source files for require path 'fs' in file index.ts.
    
  4. Cheatoid commented on Jan 31, 2026

    @Cheatoid
    Contributor

    error TSTL: Could not resolve lua source files for require path 'fs' in file index.ts.

    That's actually normal, there is no fs binding in tstl. You need to make/use declarations for your Lua environment.

  5. Freed-Wu commented on Jan 31, 2026

    @Freed-Wu
    Author

    there is no fs binding in tstl.

    1. @types/node and lua-types conflict, due to repeated definition like require.
    2. if we use two tsconfig.json for tsc and tstl, @types/node is OK for tsc, However, we need *.d.ts for fs. Even if we add @types/node, it doesn't have any lua source, which will result in error TSTL: Could not resolve lua source files for require path 'fs' in file index.ts.
  6. Zamiell commented on Jan 31, 2026

    @Zamiell
    Contributor

    @types/node and lua-types conflict, due to repeated definition like require.

    Yeah, that's a big problem. Sounds like you are running up against some fundamental technical limitations, as TypeScript isn't meant to be used this way. I think you would have to make your own types library called "lua-and-node-types" that combined exactly what you needed from both types libraries.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions