Use `keyof` when a property name must belong to a particular TypeScript type. It produces a union of that type’s property names. For a `Product` with `name: string` and `price: number`, `keyof Product` is `"name" | "price"`. A variable of that type accepts either name, but assigning `"someOtherName"` produces a compiler error. section 13.4.1
Constrain a property argument
In `src/index.ts`, a generic function can accept only keys present on its argument: function getValue<T, K extends keyof T>(item: T, keyname: K) { console.log(`Value: ${item[keyname]}`); } For a `Product`, `keyname` can be `"name"` or `"price"`; for an `Employee`, it can be `"name"` or `"role"`. Type arguments are normally inferred. If written explicitly as `getValue<Product, "name">(p, "name")`, the first `"name"` is a type argument used for checking; the second is the value passed at runtime. section 13.4.1 section 13.4.2
`keyof` supplies names, not property value types. Combine it with indexed access: `Product["price"]` is `number`, while `Product[keyof Product]` is `string | number`. In a generic getter, `K extends keyof T` checks the key and return type `T[K]` preserves the selected property’s type. section 13.4.3
Listing 13.12 Using the indexed access operator in the index.ts file in the src folder
import { City, Person, Product, Employee } from "./dataTypes.js";
function getValue<T, K extends keyof T>(item: T, keyname: K): T[K] {
return item[keyname];
}
let p = new Product("Running Shoes", 100);
console.log(getValue<Product, "name">(p, "name"));
console.log(getValue(p, "price"));
let e = new Employee("Bob Smith", "Sales");
console.log(getValue(e, "name"));
console.log(getValue(e, "role"));
The getter listing shows `keyof` restricting the argument and `T[K]` typing the returned value. section 13.4.3
The same pairing lets a collection choose its storage key instead of requiring every object to have a `name` property. With `Collection<T, K extends keyof T>`, the chosen property name has type `K`, and the map key and `get` argument use `T[K]`. Choosing a product’s `price` makes `get(100)` a numeric lookup; the compiler can infer the generic arguments from the constructor call. section 13.4.4
Mapped types use `keyof` to enumerate properties. `{ [P in keyof Product]: Product[P] }` recreates the product’s property names and types. To keep selected properties, constrain `K` with `keyof T` and map `[P in K]: T[P]`; the built-in `Pick<T, K>` serves the same selection role, while `Omit<T, K>` excludes named properties. section 13.5 section 13.5.4
Check which type receives `keyof`. If a generic argument is `Product[]`, `keyof` yields array property names—not `Product` property names—so `"price"` fails as its key. A conditional type using `infer` can extract the array element type before applying `keyof`, giving both `Product` and `Product[]` the `"name" | "price"` key union. section 13.6.6
