typedi icon indicating copy to clipboard operation
typedi copied to clipboard

fix: non-injected array class parameter throws error

Open hoonoh opened this issue 3 years ago • 0 comments

Description

If non-injected array parameter exist in class constructor, TypeDI throws error.

Minimal code-snippet showcasing the problem

import 'reflect-metadata';

import Container, { Inject, Service, Token } from 'typedi';

const token = new Token('token');
Container.set(token, 'tokenValue');

@Service()
export class Test {
  constructor(
    @Inject(token) injected: string,
    // string array parameter
    notInjected?: string[],
  ) {
    console.log('injected:', injected);
    console.log('notInjected:', notInjected);
  }
}

Container.get(Test);
/*
.../node_modules/src/container-instance.class.ts:75
    throw new ServiceNotFoundError(identifier);
          ^
ServiceNotFoundError: Service with "MaybeConstructable<Array>" identifier was not found in the container. Register it before usage via explicitly calling the "Container.set" function or using the "@Service()" decorator.
    at ContainerInstance.get (.../node_modules/src/container-instance.class.ts:75:11)
    at .../node_modules/src/container-instance.class.ts:334:21
    at Array.map (<anonymous>)
    at ContainerInstance.initializeParams (.../node_modules/src/container-instance.class.ts:314:23)
    at ContainerInstance.getServiceValue (.../node_modules/src/container-instance.class.ts:277:27)
    at ContainerInstance.get (.../node_modules/src/container-instance.class.ts:54:36)
    at Function.get (.../node_modules/src/container.class.ts:61:32)
    at Object.<anonymous> (.../services/api/src/zz.ts:20:11)
    at Module._compile (internal/modules/cjs/loader.js:1072:14)
    at Module.m._compile (.../node_modules/ts-node/src/index.ts:1365:23) {
  normalizedIdentifier: 'MaybeConstructable<Array>'
}
*/

Expected behavior

If non-injected parameter is not an array, error is not thrown:

import 'reflect-metadata';

import Container, { Inject, Service, Token } from 'typedi';

const token = new Token('token');
Container.set(token, 'tokenValue');

@Service()
export class Test {
  constructor(
    @Inject(token) injected: string,
    // string parameter
    notInjected?: string,
  ) {
    console.log('injected:', injected);
    console.log('notInjected:', notInjected);
  }
}

Container.get(Test);
/*
injected: tokenValue
notInjected: undefined
*/

A workaround to above failure is to define non-injected parameter with union with another type. For example, notInjected: string[] | undefined instead of notInjected?: string[]

hoonoh avatar Oct 20 '21 11:10 hoonoh