TypeScript映射类型中`in`关键字的作用及准确定义咨询
in Keyword in TypeScript Mapped Types Hey there! I totally get wanting a precise definition for this—since it's easy to mix up with the JavaScript in operator, and sometimes the docs can feel scattered when you're hunting for specifics. Let's break this down clearly.
Exact Definition
In TypeScript mapped types, the in keyword acts as a type-level iterator. It takes a union type (like the one returned by keyof T, or a custom union you define) and iterates over each member of that union, using each member as a property name in the new mapped type you're creating.
Basic Example
The most common use case pairs in with keyof to transform an existing object type. For example, TypeScript's built-in Readonly<T> type relies on this pattern:
type Readonly<T> = { readonly [P in keyof T]: T[P]; };
Here's the play-by-play:
keyof Tgenerates a union of all property names from typeT[P in keyof T]usesinto loop through every property namePin that union- For each
P, we create areadonlyproperty on the new type, with the same type asT[P]
Custom Union Example
You don't have to stick to keyof—you can use any union type with in to generate a type with exactly the properties you want:
type SnackFlavors = "chocolate" | "vanilla" | "strawberry"; type SnackStock = { [Flavor in SnackFlavors]: number; }; // Result: { chocolate: number; vanilla: number; strawberry: number; }
This is great for enforcing a type has a fixed set of predefined properties.
Key Difference from JavaScript's in
Don't mix this up with the JavaScript in operator! The JS version checks if a property exists on an object at runtime. The TypeScript mapped type in is purely a compile-time, type-level operation—it never touches your runtime code.
Advanced: Remapping with as (TypeScript 4.1+)
You can even tweak property names while iterating by pairing in with as. This lets you build super flexible mapped types:
type GetterMethods<T> = { [P in keyof T as `get${Capitalize<string & P>}`]: () => T[P]; }; interface Product { id: string; price: number; } type ProductGetters = GetterMethods<Product>; // Result: { getId: () => string; getPrice: () => number; }
Here, in still loops through each property in keyof Product, but as lets us transform the property name into a getter method name.
Core Takeaways
inin mapped types is a type-level tool for iterating over union types- It generates property names in a new type from each member of the union
- Pair it with
keyofto transform existing object types, or use custom unions for fixed property sets - It's entirely compile-time—no runtime behavior attached
内容的提问来源于stack exchange,提问作者jddxf

