Skip to content

tsconfig seems to be ignored #15201

@JensClasen

Description

@JensClasen

Describe the bug

Hey all,

I'm trying to use inversifyJS (a DI container) together with vite. inversify heavily depends on decorators, therefor nothing will work, unless experimental decorators are enabled for almost all compilations.

This is my current file layout:
image

In my one existing tsconfig.json, I have these settings:

{
  "compilerOptions": {
    "jsx": "react",
    "target": "ES2022",
    "useDefineForClassFields": true,
    "module": "ESNext",
    "lib": ["ES2022", "DOM", "DOM.Iterable"],
    "skipLibCheck": true,
    "types": ["reflect-metadata"],
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,    
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "resolveJsonModule": true,
    "isolatedModules": false,
    "noEmit": true,
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true
  },
  "include": ["src"]
}

The workflow starts as usual in /src/main.tsx:

import "reflect-metadata";
import React from 'react'
import ReactDOM from 'react-dom/client'

import App from "./components/App";
export function LoadReact(){
    ReactDOM.createRoot(document.getElementById('app')!).render(
    <React.StrictMode>
        <App />
    </React.StrictMode>,
    )
}

and it hops from there over to /components/App.tsx:

import { container } from '../inversify.config';
import React from 'react';
import { IClientApplication, Symbol_IClientApplication } from '../model/contract/IClientApplication';

export default function App() {
  const app : IClientApplication = container.get<IClientApplication>(Symbol_IClientApplication);
  return (<>{app.translate("Hello world")}</>);
}

From there, the DI container config in /inversify.config.tsx is imported:

// DI container: 
import { Container } from "inversify";
const container = new Container();

// contract:
import { IClientApplicationConfig, Symbol_IClientApplicationConfig } from "./model/contract/IClientApplicationConfig.tsx";

// implementations
import { ClientApplicationConfig } from "./model/ClientApplicationConfig.tsx";
container.bind<IClientApplicationConfig>(Symbol_IClientApplicationConfig).to(ClientApplicationConfig).inSingletonScope();

import { IClientApplication, Symbol_IClientApplication } from "./model/contract/IClientApplication.tsx";
import { ClientApplication } from "./model/ClientApplication.tsx";
container.bind<IClientApplication>(Symbol_IClientApplication).to(ClientApplication);

export { container };

This is followed by an import for my application contract in /model/contract/IClientApplicationConfig.tsx:

export interface IClientApplication{
    translate(value:string):string;
}
export const Symbol_IClientApplication = Symbol.for("IClientApplication");

Having done all that, the container should be used to initialize my sample application in /model/ClientApplication.tsx:

import { inject } from "inversify";
import { IClientApplication } from "./contract/IClientApplication";
import { IClientApplicationConfig, Symbol_IClientApplicationConfig } from "./contract/IClientApplicationConfig";

export class ClientApplication implements IClientApplication{
    constructor(
        @inject(Symbol_IClientApplicationConfig) private _config:IClientApplicationConfig
    ) {
    }
    translate(value: string): string {
        return "irrelevant markdown breaking stuff";
    }
}

To create an instance of my application, the DI container must use constructor property injection and therefor the experimental decorators.

The config implementation in /model/ClientApplicationConfig.tsx is again just a little sample:

import { injectable } from "inversify";
import { IClientApplicationConfig } from "./contract/IClientApplicationConfig";

@injectable()
export class ClientApplicationConfig implements IClientApplicationConfig{
    public clientName : string = "";
    public clientVersion: string = "0.0.0.0";
    public backendUrl:string ="/api/v1/";
}

According to all the docs, this should work. At least I'd have thought so. Instead, this is what happens:


> test@0.0.0 dev
> vite


  VITE v5.0.4  ready in 231 ms

  ➜  Local:   http://localhost:5173/
  ➜  Network: use --host to expose
  ➜  press h + enter to show help
Error:   Failed to scan for dependencies from entries:
  /home/user/playground/explanation/index.html

  ✘ [ERROR] Parameter decorators only work when experimental decorators are enabled

    src/model/ClientApplication.tsx:10:8:
      10 │         @inject(Symbol_IClientApplicationConfig) private _config:I...
         ╵         ^

  You can enable experimental decorators by adding "experimentalDecorators": true to your "tsconfig.json" file.

Especially the last line bothers me since my tsconfig.json does contain the necessary line. It therefor stands to reason, that my tsconfig.json is not found at all.

If I now change my folder structure and place every file in the src directory:

image

Then the error is gone and npm run dev works without problems.

The behavior smells a bit like #7932. Neither the explanation, nor the workaround seem to fit, though. I'm stepping not out of the project root in my case. I'm working in three of it's subfolders. I would have expected, that the tsconfig should have been found.

I did not manage to get the workaround from #7932 to work. Even if I had managed to do so, a package.json in every folder is no workable solution.

Any ideas?
Regards, Jens

Reproduction

part of the description

Steps to reproduce

No response

System Info

System:
    OS: Linux 6.4 Arch Linux
    CPU: (4) x64 Intel(R) Core(TM) i5-7300U CPU @ 2.60GHz
    Memory: 7.25 GB / 15.50 GB
    Container: Yes
    Shell: 3.6.1 - /usr/bin/fish
  Binaries:
    Node: 20.5.0 - /usr/bin/node
    npm: 9.8.1 - /usr/bin/npm
  npmPackages:
    vite: ^5.0.0 => 5.0.4

Used Package Manager

npm

Logs

No response

Validations

Metadata

Metadata

Assignees

No one assigned

    Labels

    has workaroundp2-edge-caseBug, but has workaround or limited in scope (priority)regressionThe issue only appears after a new release

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions