Reputation: 374
Why do I get errors in e4
, e5
, e6
? All of them match SomeClass
type so they have to match generic RES
.
class SomeClass {
a: string;
b: number;
c: boolean;
}
class ChildOfSomeClass extends SomeClass {}
const someFunc1 = <RES extends SomeClass>() => {
const e1: SomeClass = { a: "aaa", b: 123, c: true }; // ok
const e2: SomeClass = new SomeClass(); // ok
const e3: SomeClass = new ChildOfSomeClass(); // ok
// Type '{ a: string; b: number; c: true; }' is not assignable to type 'RES'.ts(2322)
const e4: RES = { a: "aaa", b: 123, c: true };
// Type 'SomeClass' is not assignable to type 'RES'.ts(2322)
const e5: RES = new SomeClass();
// Type 'ChildOfSomeClass' is not assignable to type 'RES'.ts(2322)
const e6: RES = new ChildOfSomeClass();
};
I eventually want someFunc1
to return RES | Promise<RES>
but for the sake of the example, I simplified it.
Upvotes: 0
Views: 70
Reputation: 149058
RES extends SomeClass
means that the set of values described by type RES
is a subset of the set of values described by type SomeClass
. Imagine the following scenario:
class MyRES extends SomeClass {
d: string;
}
This satisfies the condition RES extends SomeClass
, however in none of the constructor cases you've provided do you assign d
.
There are many ways to approach this problem, and the "correct" solution will depend on what exactly you're trying to accomplish with this method. For example, one solution would be to make your method take some constructor or converter method to create a RES
from the known existing properties of SomeClass
:
const someFunc1 = <RES extends SomeClass>(toRes: (SomeClass) => RES) => {
const e: RES = toRes({ a: "aaa", b: 123, c: true }); // ok
};
Upvotes: 2
Reputation: 40700
This is because RES
extends SomeClass
. Imagine the following:
class SomeClass {
a: string;
b: number;
c: boolean;
}
class ChildOfSomeClass extends SomeClass {}
class OtherChild extends SomeClass { d: string }
And imagine that RES
is OtherChild
(which does extend SomeClass
) your code would then look like:
const someFunc1 = () => {
const e1: SomeClass = { a: "aaa", b: 123, c: true }; // ok
const e2: SomeClass = new SomeClass(); // ok
const e3: SomeClass = new ChildOfSomeClass(); // ok
const e4: OtherChild = { a: "aaa", b: 123, c: true }; // Not OK, OtherChild needs d
// Downcasting SomeClass to OtherChild is not ok
const e5: OtherChild = new SomeClass();
const e6: OtherChild = new ChildOfSomeClass(); //This is especially not OK
};
You could solve this by just using SomeClass
and then passing any child object will be ok.
Upvotes: 1