Consider the following class and a factory method with two implementations
class SomeClass {
public someId: number;
public someProp: string;
constructor(input) {
// do some internal stuff with input;
}
}
function factory(singleInput: {}): SomeClass;
function factory(multipleInput: Array<{}>): Array<SomeClass>;
function factory(singleOrMultipleInput: {} | Array<{}>): SomeClass | Array<SomeClass> {
if (singleOrMultipleInput instanceof Array) {
// case multiple input: Array<{}>
const arrayOfSomeClass = singleOrMultipleInput.map(ro => new SomeClass(singleOrMultipleInput)); // indeed is shown as SomeClass[]
return arrayOfSomeClass;
} else {
// case single input: {}
const singleSomeClass = new SomeClass(singleOrMultipleInput); // indeed is shown as SomeClass
return singleSomeClass;
}
}
In words: when calling factory with a {} as parameter (a plain object), I want it to return an instance of SomeClass. When calling factory with an array of objects, [{}, {}, {}], I want it to return a array of instances of SomeClass, like [SomeClass, SomeClass, SomeClass].
The snippet below shows that the TypeScript interpreted doesn't recognise it as such.
const singleInput: {} = {};
const multipleInput: Array<{}> = [{}, {}, {}];
let singleResult = factory({}); // is SomeClass, as expected
const multipleResult = factory([{}]); // no longer is SomeClass[] ?!
singleResult.someId = 123;
multipleResult.someId = 456; // the interpreter should flag this as wrong
singleResult = multipleResult; // also shouldn't be possible without an warning from the interpreter
However, within the factory method, arrayOfSomeClass and singleSomeClass are typed correctly. Why does multipleResult not show as SomeClass[] by the interpreter?
Follow up question: how can it be implemented such that the interpreter shows the types as I would expected? (preferably having the factory method as a static (generic?) method of SomeClass (I realise this can probably be achieved by avoiding overloading, but thats not what I'm looking for)