Consider the following class
class SomeBaseClass<T extends string | number> {
...
}
And the following conditional type using the infer keyword
type ExtractInner<T> = T extends SomeBaseClass<infer U> ? U : T;
With this, we can extract the generic type used in SomeBaseClass like this (this is from the docs, more or less)
type InferredString = ExtractInner<SomeBaseClass<string>> // InferredString is just type string
In my slightly more advanced scenario, the following is the case
class StringVersion extends SomeBaseClass<string> {
...
}
class NumberVersion extends SomeBaseClass<number> {
...
}
How may one define a type ExtractInnerWithExtend such that it is the equivalent to ExtractInner? I.e.:
type InferredStringWithExtend = ExtractInnerWithExtend<StringVersion> // InferredStringWithExtend should be string
type InferredNumberWithExtend = ExtractInnerWithExtend<NumberVersion> // InferredStringWithExtend should be number
Using ExtractInner in this scenario will result in simply string | number, I was actually expecting to get either string or number, not the union type. Is this maybe a bug? Is what I'm trying possible?
Many thanks in advance.
ExtractInner will work on the derived version of the types with one condition: that you actually use the type in the base class in some way
class SomeBaseClass<T extends string | number> {
private value!: T
// Any of these will also work
//value!: T
//m(v:T): void {}
//m(): T { return null as any }
}
type ExtractInner<T> = T extends SomeBaseClass<infer U> ? U : T;
class StringVersion extends SomeBaseClass<string> {}
class NumberVersion extends SomeBaseClass<number> {}
type InferredStringWithExtend = ExtractInner<StringVersion> // string
type InferredNumberWithExtend = ExtractInner<NumberVersion> // number
The reason for this behavior is the structural nature of the typescript type system, type structure matters more then the inheritance declarations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With