say we have the following code :
class Foo<T> {
lift<R>(): Foo<R> {
const bar = new Foo<T>()
return bar
}
}
why there is no error? Foo<T> and Foo<R> may be different type.
CodePudding user response:
TS uses structural type matching and not nominal. This means that 2 types are compatible if their structure is compatible.
You can read about how matching happens for generics here.
The reason your example works is that from a structure point of view there isn't anything that differentiates between Foo<string> or Foo<number> for instance. This is gonna work in TS
const a: Foo<string> = new Foo<number>()
This is also the reason why your function works, because Foo<TypeA> is compatible with Foo<TypeB> for any TypeA and TypeB.
If you add anything else that use T then the structural compatibility is broken and you get the error you are expecting:
class Foo<T> {
field: T | null = null
lift<R>(): Foo<R> {
const bar = new Foo<T>()
return bar
}
}
Type 'Foo<T>' is not assignable to type 'Foo<R>'.
Type 'T' is not assignable to type 'R'.
'R' could be instantiated with an arbitrary type which could be unrelated to 'T'.(2322)
You can see this in action here
