Typescript extends keyword explained
Typescript extends
keyword is very powerful and helpful, it avoids unnecessary type properties duplication and also helps with type specificity. Here are the 2 prominent cases of using the extends
keyword.
Inheritance
In some cases, we have an interface that is just an extension of another interface with additional properties, the extends
keyword makes the child interface inherit properties from the parent interface. For example
interface Animal {
name: string,
weight: number,
}
interface Honeybadger {
name: string,
weight: number,
skin: string,
color: string,
}/**
we can avoid duplication on the HoneyBadger by using the
typescript extends keyword
*/interface Honeybadger extends Animal {
skin: string,
color: string,
}/**
Honeybadger inherits name and weight attributes from Animal, but also has
the skin and color property as well
*/
Generics Constraints
Some types we create can be reusable with other types, to avoid duplicating types for each use case, we can use a generic type. Generics are used to create reusable types, as parameters are to functions, so are generics to types.
For example, we can create a generic type function that receives a parameter of T
and reuse that type within different contexts.
type Log<T> = (content: T) => void
// Log T = string
const consoleString: Log<string> = (content) => console.log(content)// Log T = {error: string}
const consoleError: Log<{error: string}> = (content) => console.error(content)
However, we sometimes want to limit or constrain the generic type that can be used or passed, and the extends
shines in this regard. For example
type Log<T extends {name: string}> = (content: T) => void
/** ❌ throws error
Type 'string' does not satisfy the constraint '{ name: string; }'
*/
const consoleString: Log<string> = (content) => console.log(content)type User = {
name: string
}type Animal = {
name: string;
age: number;
}// ✅ passes
const consoleName: Log<User | Animal> = (content) => console.log(content.name)
In the code snippets above, type Log
accepts a generic type T
, but there is a condition on T
, the condition using the extends
keyword which states that T
must have at least property name
of type string
, so T
cannot be of type string
or any other type that doesn’t have the property specified.
One key thing to notice is that the constraint on the type doesn’t have to be exact, the type Animal
for example, still passes even though it has age as an additional property.