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