This TypeScript error occurs when using mapped types incorrectly, typically by forgetting or misusing the required "in" syntax for iterating over keys. The error prevents compilation and indicates a syntax violation in mapped type definitions.
The error "Mapped type property must be computed using 'in' syntax" occurs when TypeScript encounters invalid syntax in a mapped type definition. Mapped types are a powerful TypeScript feature that allows you to create new types by transforming properties of existing types. In TypeScript, mapped types use a specific syntax pattern: `[Property in keyof Type]` where you iterate over the keys of a type. This error appears when you attempt to define a mapped type without using the proper "in" syntax, or when you use incorrect syntax that TypeScript cannot parse as a valid mapped type. The error is a syntax error, not a type error, meaning it occurs during parsing rather than type checking. This usually happens when: 1. Forgetting the "in" keyword entirely 2. Using incorrect syntax like `[Property: keyof Type]` instead of `[Property in keyof Type]` 3. Mixing up mapped type syntax with index signature syntax 4. Using mapped types in contexts where they're not allowed Mapped types were introduced in TypeScript 2.1 and have evolved with additional features in later versions, but the core "in" syntax remains mandatory for all mapped type definitions.
First, examine your mapped type definition to ensure it uses the correct in syntax. The basic pattern is:
// Correct syntax
type MappedType<T> = {
[K in keyof T]: T[K];
};
// Incorrect syntax (causes error)
type WrongType<T> = {
[K: keyof T]: T[K]; // Error: Mapped type property must be computed using 'in' syntax
};Make sure you're using in not : between the property variable and the key source.
Mapped types can only be used in type aliases, interfaces, and type parameters. They cannot be used in value positions or runtime code.
// Allowed: Type alias
type Readonly<T> = { readonly [K in keyof T]: T[K] };
// Allowed: Interface
interface ReadonlyInterface<T> {
readonly [K in keyof T]: T[K];
}
// Not allowed: In function return type (without type alias)
function createReadonly<T>(obj: T) {
return { readonly [K in keyof T]: T[K] }; // Error
}If you need to use mapped types in function signatures, define them as separate type aliases first.
For advanced mapped types with modifiers or conditional logic, ensure the syntax is correct:
// Correct: With optional modifier
type Partial<T> = { [K in keyof T]?: T[K] };
// Correct: Removing readonly modifier
type Mutable<T> = { -readonly [K in keyof T]: T[K] };
// Correct: Key remapping with 'as' (TypeScript 4.1+)
type Getters<T> = {
[K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
};
// Incorrect: Missing proper syntax
type Wrong<T> = {
[K keyof T]?: T[K]; // Missing 'in' keyword
};Pay special attention to:
- The in keyword after the property variable
- Proper use of keyof operator
- Correct placement of modifiers (?, readonly, -readonly, -?)
- Valid use of as clause for key remapping
Don't confuse mapped types with index signatures. They have different syntax and purposes:
// Index signature (for objects with dynamic keys)
interface StringDictionary {
[key: string]: string; // Uses colon (:)
}
// Mapped type (for transforming existing types)
type ReadonlyDictionary<T> = {
[K in keyof T]: T[K]; // Uses 'in'
};
// Common mistake: mixing the syntax
type Wrong<T> = {
[K: keyof T]: T[K]; // Error: This looks like an index signature but uses keyof
};Remember:
- Index signatures use [key: type]: valueType syntax
- Mapped types use [K in keyof T]: transformedType syntax
- They serve different purposes and cannot be mixed
When in doubt, use the TypeScript Playground to test your mapped type syntax:
1. Go to https://www.typescriptlang.org/play
2. Paste your mapped type code
3. Check for errors in the editor
4. Experiment with different syntax variations
Example test:
// Test this in playground
type TestType<T> = {
[K in keyof T]: T[K];
};
interface Example {
name: string;
age: number;
}
type TestResult = TestType<Example>;
// Should produce: { name: string; age: number; }The playground provides instant feedback and helps you understand the correct syntax.
Some mapped type features require specific TypeScript versions:
- Basic mapped types: TypeScript 2.1+
- Conditional types with mapped types: TypeScript 2.8+
- Key remapping with as: TypeScript 4.1+
- Template literal types in mapped types: TypeScript 4.1+
Check your TypeScript version:
npx tsc --version
# or
npm list typescriptUpdate if needed:
npm install typescript@latest --save-devEnsure your tsconfig.json targets a compatible version and that your IDE uses the same TypeScript version as your project.
## Understanding the Compiler Perspective
From TypeScript's compiler perspective, mapped types are parsed differently than index signatures. The parser expects to see the pattern [ Identifier in Type ] for mapped types. When it encounters [ Identifier : Type ] in a type position, it interprets it as an index signature, but keyof T is not a valid type for an index signature parameter (which must be string, number, symbol, or a template literal type).
## Historical Context
Mapped types were introduced in TypeScript 2.1 (November 2016) and have evolved:
- TypeScript 2.1: Basic mapped types [K in keyof T]
- TypeScript 2.8: Conditional types and improved mapped type modifiers
- TypeScript 4.1: Key remapping with as clause and template literal types
- TypeScript 4.3: Separate write types on mapped types
## Common Pitfalls
1. Generic Constraints: When using mapped types with generic constraints, ensure the constraint allows key iteration:
type MapKeys<T extends Record<string, any>> = { [K in keyof T]: T[K] };2. Mapped Types with never: Creating mapped types over never produces {} (empty object type).
3. Homomorphic vs Non-homomorphic: Mapped types over keyof T are homomorphic (preserve structure), while those over arbitrary unions are not.
4. Distributive Conditional Types: When combined with conditional types, mapped types can have distributive behavior over union types.
Type parameter 'X' is not used in the function signature
How to fix "Type parameter not used in function signature" in TypeScript
Type parameter 'X' is defined but never used
How to fix "Type parameter is defined but never used" in TypeScript
Function expression requires a return type
Function expression requires a return type
Value of type 'string | undefined' is not iterable
How to fix "Value is not iterable" in TypeScript
Type 'undefined' is not assignable to type 'string'
How to fix "Type undefined is not assignable to type string" in TypeScript