typescript - infer-nyckelord för att få generisk typ från basklass
Betrakta följande klass
class SomeBaseClass<T extends string | number> {
...
}
Och följande konditionella typ som använder infer-nyckelordet
type ExtractInner<T> = T extends SomeBaseClass<infer U> ? U : T;
Med detta kan vi extrahera den generiska typen som används i SomeBaseClass på detta sätt (detta är mer eller mindre från dokumentationen)
type InferredString = ExtractInner<SomeBaseClass<string>> // InferredString is just type string
I mitt något mer avancerade scenario är följande fallet
class StringVersion extends SomeBaseClass<string> {
...
}
class NumberVersion extends SomeBaseClass<number> {
...
}
Hur kan man definiera en typ ExtractInnerWithExtend så att den motsvarar ExtractInner? D.v.s.:
type InferredStringWithExtend = ExtractInnerWithExtend<StringVersion> // InferredStringWithExtend should be string
type InferredNumberWithExtend = ExtractInnerWithExtend<NumberVersion> // InferredStringWithExtend should be number
Att använda ExtractInner i detta scenario kommer helt enkelt att resultera i string | number, jag förväntade mig faktiskt att få antingen string eller number, inte unionstypen. Är detta kanske en bugg? Är det jag försöker göra möjligt?
Stort tack i förväg.
Svar #1
ExtractInner kommer att fungera på den härledda versionen av typerna med ett villkor: att du faktiskt använder typen i basklassen på något sätt
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
Anledningen till detta beteende är den strukturella naturen hos TypeScript-typsystemet, typstruktur är viktigare än arvdeklarationerna.
