Hint
TypeScript infers function return types from the return expression, not from what you wish it returned. This means ReturnType<typeof makeUser> gives you the exact shape including all fields — even dynamically added ones.
// Simulate what ReturnType<T> extracts at runtime
function makeUser(name, age) {
return { name, age, createdAt: new Date('2024-01-01').toISOString() };
}
function makeProduct(title, price) {
return { title, price, inStock: true };
}
// ReturnType would give: { name: string; age: number; createdAt: string }
// Simulate by actually calling and logging keys
const user = makeUser('Alice', 30);
const product = makeProduct('Widget', 9.99);
// Log the inferred shape
console.log(Object.keys(user).sort().join(','));
console.log(Object.keys(product).sort().join(','));
// TypeScript uses the return value's shape — not what you annotate
function identity(x) { return x; }
const val = identity(42);
console.log(typeof val);age,createdAt,name inStock,price,title number
Explanation: Object.keys returns the actual property names. TypeScript infers ReturnType from the concrete return expression — makeUser returns an object with name, age, createdAt. identity(42) returns number because 42 is number.
Key Insight: TypeScript infers function return types from the return expression, not from what you wish it returned. This means ReturnType