I’m trying to write a utility function in my TypeScript project to sort/filter objects in a fairly predictable data model (I’m using Astro for this site). The objects keep all the data useful for sorting/filtering in the data
property.
I cannot figure out how to properly type this function, which takes a collection of objects and the name of a property as arguments: foo( collection, property ) { ... }
.
Here’s a super simplified version of what I’ve been trying to do. It doesn’t take a collection as the first arg, but the gist is the same: I want to pass in the name of a property in data
and then access the value of that property.
interface User {
data: {
id: number;
name: string;
}
}
interface House {
data: {
number: number;
street: string;
}
}
type Obj = User | House;
function getProperty<
T extends Obj,
K extends keyof T['data']
>(obj: T, key: K): T['data'][K] {
return obj.data[key];
// Type 'K' cannot be used to index type '{ id: number; name: string; } | { number: number; street: string; }'.ts(2536)
}
const user: User = { data: { id: 1, name: "Alice" }};
const house: House = { data: { number: 2, street: "First" }};
const userName = getProperty(user, "name");
const houseNumber = getProperty(house, "number");
TypeScript understands what’s going on with the function, as the last two lines won’t let me pass in a property name that isn’t in the corresponding object’s data. But for the life of me, I don’t know how to get K
to behave.