I created a custom configuration file for my NestJs REST API. This is a simple example for the port the application is listening on.
I have a .env file with the content
SERVER_PORT = 3000
An example for my configuration file
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import * as Joi from '@hapi/joi';
@Injectable()
export class ServerConfigService {
constructor(private readonly configService: ConfigService) {
const { error } = Joi.object({
port: Joi.number()
.port()
.required(),
}).validate({ port: this.port });
if (error) { // no error thrown
throw error;
}
console.log(typeof this.port); // type is string but should be number
}
public get port(): number {
return this.configService.get<number>('SERVER_PORT');
}
}
I would expect the ports type to be number
but it's still a string
. So two things come to my mind:
this.configService.get<T>('key')
as shown here with a generic type. Why does it still return a string? I would expect a type cast.The port variable might be a bad example because Nest is able to deal with a port of type string. But other parts expect numbers and throw errors if a config variable should be a number but is of type string.
Did I miss something?
The example you found using the ConfigService
is very misleading. What's misleading is the generic type parameter. The type you pass it only affects what the return value is treated as. The actual runtime type will be whatever the type is when it was read.
NestJs uses dotenv
to read the config files and all values are simply read as strings. No conversions are made.
You should be using it like this:
public get port(): number {
return +this.configService.get('SERVER_PORT');
}