Let's analyze the Typescript code provided below:
class OrderFixture {
orderId: string;
constructor() {
this.orderId = "foo";
}
}
class DecisionFixture {
decisionId: string;
constructor() {
this.decisionId = "bar";
}
}
class FixtureStore {
order = () => new OrderFixture();
decision = () => new DecisionFixture();
}
const fixtureStore = new FixtureStore();
export function getFixture<
K extends keyof FixtureStore,
T extends ReturnType<FixtureStore[K]>
>(entityName: K): T {
return fixtureStore[entityName](); // ERROR: Type 'OrderFixture' is not assignable to type 'T'.
}
A type error is generated as a result of the code snippet above, displaying the following message:
Type 'OrderFixture | DecisionFixture' is not assignable to type 'T'.
'OrderFixture | DecisionFixture' can be assigned to type 'T', but another subtype of constraint 'OrderFixture | DecisionFixture' might potentially replace 'T'.
Type 'OrderFixture' does not align with type 'T'.
'OrderFixture' can fit into type 'T', however, an alternative subtype of constraint 'OrderFixture | DecisionFixture' could possibly replace 'T'.ts(2322)
You can experiment with the code on the playground.
If you reference this answer, there appears to be a well-defined solution to this type of error. However, I am currently unable to identify any similarities between those scenarios and the issue presented in my code.
Upon attempting to forcefully convert the return value to T
as recommended in this response, the correct types are obtained when calling getFixture
. Why doesn't TypeScript automatically deduce these types for me?