I have an interface inheritence hierarchy like this:
interface IBase { type: stirng; }
interface IDerived1 extends IBase { type: "Derived1"; }
interface IDerived2 extends IBase { type: "Derived2"; }
...
These are actually generated interfaces for C# types, that's why the type
discriminator property on them.
Is it possible to wirte a type in TypeScript for all the possible type
string literal values,
based on the existing type hierarchy only,
so without specifying them manually one by one?
I would like to get smg like this:
type AllTypesOf<T extends {type: string}> = /* ? what comes here ? */;
...
const myVar: AllTypesOf<IBase>; // "Derived1" | "Derived2" | ...
Which I'd use like this:
function mySwitch(myArg: IBase) {
const type = myArg.type as AllTypesOf<IBase> // "Derived1" | "Derived2" | ...
switch(type) {
case "Derived1":
case "Derived2":
// ok
case "Derived3":
// NOK, error, does not exist such
}
}
CodePudding user response:
TypeScript follows basic inheritance rules: parents don't know anything about their children. You could make an Enum of all the values, and then reference them in your types:
enum AllTypesOf {
DERIVED_1 = "Derived1",
DERIVED_2 = "Derived2"
}
interface IBase { type: AllTypesOf }
interface IDerived1 extends IBase { type: AllTypesOf.DERIVED_1 }
function mySwitch(myArg: IBase) {
const type = myArg.type // Automatically typed as AllTypesOf
switch(type) {
case AllTypesOf.DERIVED_1:
case AllTypesOf.DERIVED_2:
// ok
case AllTypesOf.DERIVED_3: // error, does not exist in enum
// NOK, error, does not exist such
}
}
CodePudding user response:
For this a union type alias would make a lot of sense.
For example, with the types you specified in your question such a union type alias could look like this:
// Your types
interface IBase { type: stirng; }
interface IDerived1 extends IBase { type: "Derived1"; }
interface IDerived2 extends IBase { type: "Derived2"; }
// The new alias:
type ICombined = IDerived1 | IDerived2;
This new type ICombined
can then be used as you intended. To get for instance a type entirely made up of the strings that are possibilities for the type
field, you can write ICombined["type"]
.
With the switch statement as an example, the type inference works as well, and trying to use a string that isn't an option for the type
field results in a
Type '"some string"' is not comparable to type '"Derived1" | "Derived2"'
compiler error.