I'd like to write a function that returns a property of an extended generic type. Is it even possible?
Here's what I've tried:
interface Animal {
readonly weight: {total: number}
}
interface Dog extends Animal {
readonly weight: {total: number, tail: number, head: number, body: number }
}
const getWeight = <T extends Animal>(animal: T) => {
return animal.weight
}
const myDog = { weight: { total: 20, tail: 5, head: 5, body: 10 } }
const myDogsWeight = getWeight<Dog>(myDog)
// Property 'head' does not exist on type '{ total: number; }'.
const myDogsHeadWeight = myDogsWeight.head
If I try to explicitly annotate the return type of the function, I get another error:
type InferredWeight<TAnimal> = TAnimal extends { readonly weight: infer U } ? U : never
type DogWeight = InferredWeight<Dog> // <-- This type works correctly
const getWeightTyped = <T extends Animal>(animal: T): InferredWeight<T> => {
// Type '{ total: number; }' is not assignable to type 'InferredWeight<T>'.
return animal.weight
}
Here's a playground link .
The only TypeScript Github issue that seems relevant is this one , but it is an issue with union types.
As mentioned in the comment by @jcalz you can use a lookup type:
This should do what you are looking for.
interface Animal {
readonly weight: { total: number }
}
interface Dog extends Animal {
readonly weight: { total: number, tail: number, head: number, body: number }
}
const getWeight = <
T extends Animal
>(animal: T): T['weight'] => {
return animal.weight
}
const myDog = { weight: { total: 20, tail: 5, head: 5, body: 10 } }
const myDogsWeight = getWeight(myDog);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.