I am looking to create a function that can retrieve a property from an extended generic type. Is this something achievable?
Here is my attempt:
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
When I try to specify the return type of the function explicitly, I encounter 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 is a playground link.
The only TypeScript Github issue that appears relevant is this one, but it pertains to union types.