For an API I'm writing I want to make sure the values I pass around can only be instantiated by my own specific functions to ensure the validity of said values. I know the tried and true method is to create a class with a private constructor and static factory methods like the example below (hypothetical situation; the actual class is more complex and has methods).
export class ServiceEndpoint {
private constructor(
readonly name: string,
readonly address: string,
readonly port: number
) {}
static getByName(name: string): ServiceEndpoint {
// ... polling operation that results in an address
return new this(name, address, port);
}
}
But in order to allow for a more functional approach I would like the factory function to live outside of the class itself (but in the same module) in order to be able to more freely compose different variants. I came up with the following approach, where I keep the constructor public but restrict it to functions in the same module by not exporting it:
class ServiceEndpoint {
constructor(
readonly name: string,
readonly address: string,
readonly port: number
) {}
}
export function getEndpointByName(name: string): ServiceEndpoint {
// ... polling operation that results in an address
return new ServiceEndpoint(name, address, port);
}
Testing this seems to yield the same result, but I haven't seen other people do it like this so I'm a bit cautious. Am I rightfully assuming this prevents users of the module to instantiate the class on their own, just like a private constructor does? Are there disadvantages to this method I am overseeing?