In TypeScript, is it possible for a type alias to "implement" (or become subtype of) another type alias?
For example, I have the following type aliases (TS Playground Link):
type Predicate<TValue> = {
op: "EQUAL" | "NOT_EQUAL",
value: TValue,
}
type Predicates = Record<string, Predicate<string> | Predicate<boolean>>
/**
* An implementation of the {@link Predicates} type.
*/
type AnimalPredicates = {
species: Predicate<string>,
isMammal: Predicate<boolean>,
}
// EXAMPLE:
const animalPredicates: AnimalPredicates = {
species: { op: "EQUAL", value: "shiba_inu" },
isMammal: { op: "EQUAL", value: true },
}
// `AnimalPredicates` is a subtype of `Predicates` so this is allowed
const animalPredicates2: Predicates = animalPredicates
The AnimalPredicates
type alias is an implementation of the Predicates
type (i.e. AnimalPredicates
is subtype of Predicates
).
Although I added a JSDoc comment saying that AnimalPredicates
implements Predicates
, it does not prevent me from doing something like:
type AnimalPredicates = {
// Predicate<number> is NOT allowed as record value in `Predicates`
// But TS compiler does not complain...
species: Predicate<number>,
}
Is there a workaround to let the TS compiler know that AnimalPredicates
must be a subtype of the Predicate
type?
>Solution :
You can make AnimalPredicates
extend Predicates
type Predicate<TValue> = {
op: "EQUAL" | "NOT_EQUAL",
value: TValue,
}
type Predicates = Record<string, Predicate<string> | Predicate<boolean>>
/**
* An implementation of the {@link Predicates} type.
*/
interface AnimalPredicates extends Predicates {
species: Predicate<string>,
isMammal: Predicate<boolean>,
}
// EXAMPLE:
const animalPredicates: AnimalPredicates = {
species: { op: "EQUAL", value: "shiba_inu" },
isMammal: { op: "EQUAL", value: true },
}
// `AnimalPredicates` is a subtype of `Predicates` so this is allowed
const animalPredicates2: Predicates = animalPredicates
see TS playground
you can also clean it a bit by restricting the generic itself
type Predicate<TValue extends string | boolean> = {
op: "EQUAL" | "NOT_EQUAL",
value: TValue,
}
/**
* An implementation of the {@link Predicates} type.
*/
interface AnimalPredicates {
species: Predicate<string>,
isMammal: Predicate<boolean>,
}
// EXAMPLE:
const animalPredicates: AnimalPredicates = {
species: { op: "EQUAL", value: "shiba_inu" },
isMammal: { op: "EQUAL", value: true },
}
see TS playground