typescripttsyringe

How to inject singleton to injectable with tsyringe?


I'm currently working with tsyringe for backend, and trying to inject singleton class to another injectable class. However, it seems that the instance of MockUserRepository that UserServiceImpl has is different from container.resolve(MockUserRepository).

This is my class definitions

@injectable()
export class UserServiceImpl implements UserService {
    constructor(
        @inject('UserRepository') private userRepository: UserRepository,
    ) {}
    // ...
}

@singleton()
export class MockUserRepository implements UserRepository {
    private readonly users: User[] = [];

    // ...
}

And this is my tsyringe setup and test code

container.register('UserRepository', {useClass: MockUserRepository}, {lifecycle: Lifecycle.Singleton });

const userService = container.resolve(UserServiceImpl);
const userRepository = container.resolve(MockUserRepository);

// create user directly to repository
await userRepository.create({
  id: 'userId'
});

// user become null
const user = await userService.getUserById('userId');

I checked that MockUserRepository is recognized as singleton by tsyringe properly:

const userRepository1 = container.resolve(MockUserRepository);
const userRepository2 = container.resolve(MockUserRepository);

// create user
await userRepository1.create({
  id: 'userId'
});
// user not become null
const user = await userRepository2.find('userId');

I started using tsyringe a little while ago so I know very little about it. How can I use same instance?


Solution

  • My guess is that the injection tokens are different. When registering, you use a string

    container.register('UserRepository', {useClass: MockUserRepository}, {lifecycle: Lifecycle.Singleton });
    

    but when you request the instance from the container, you use another symbol container.resolve(MockUserRepository).

    It's possible that if you use container.resolve('UserRepository') instead, you will get the same instance.