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.

Relaterade artiklar