Mapped types with template literals let you create new object types by changing keys using string patterns. This helps make your code flexible and reusable.
Mapped type with template literals in Typescript
type NewType<T> = {
[K in keyof T as `prefix_${string & K}_suffix`]: T[K]
};The as keyword lets you rename keys using template literal strings.
Use string & K to ensure the key is treated as a string for template literals.
type User = {
name: string;
age: number;
};
type PrefixedUser = {
[K in keyof User as `get_${string & K}`]: User[K];
};type Flags = {
isActive: boolean;
isAdmin: boolean;
};
type SuffixFlags = {
[K in keyof Flags as `${string & K}_flag`]: Flags[K];
};Uppercase utility type.type Options = {
debug: boolean;
verbose: boolean;
};
type UppercaseOptions = {
[K in keyof Options as Uppercase<string & K>]: Options[K];
};This program creates a new type where each key from Person is renamed with a 'readonly_' prefix and made readonly. Then it creates an object of that type and prints it.
type Person = {
firstName: string;
lastName: string;
age: number;
};
type ReadonlyPerson = {
readonly [K in keyof Person as `readonly_${string & K}`]: Person[K];
};
const person: ReadonlyPerson = {
readonly_firstName: "Alice",
readonly_lastName: "Smith",
readonly_age: 30
};
console.log(person);Mapped types with template literals only work with keys that can be converted to strings.
You can combine this with modifiers like readonly or ? (optional) for more control.
Template literal types are powerful for creating dynamic and descriptive keys in types.
Mapped types with template literals let you rename keys dynamically in object types.
This helps create flexible and reusable type patterns without repeating code.
Use as with template literals and string & K to transform keys safely.
Practice
What does a mapped type with template literals in TypeScript allow you to do?
Example: { [K in keyof T as `get${Capitalize}`]: () => T[K] }
Solution
Step 1: Understand mapped types
Mapped types create new object types by transforming keys or values of an existing type.Step 2: Role of template literals
Template literals let you rename keys dynamically by combining strings and key names.Final Answer:
Rename keys dynamically in object types -> Option BQuick Check:
Mapped type + template literals = dynamic key renaming [OK]
- Confusing runtime behavior with type transformations
- Thinking it changes object values instead of keys
- Assuming it creates variables or runs code
Which of the following is the correct syntax to rename keys using a mapped type with template literals?
type RenameKeys<T> = { [K in keyof T as ???]: T[K] }Solution
Step 1: Understand key remapping syntax
Useaswith template literals and intersect key type withstringto ensure keys are strings.Step 2: Check each option
`new_${string & K}` usesstring & Kwhich is correct; others use incorrect types likenumberorany.Final Answer:
`new_${string & K}` -> Option AQuick Check:
Usestring & Kfor safe key renaming [OK]
- Using K directly without string intersection
- Using number or any instead of string & K
- Missing backticks for template literals
What is the resulting type of the following code?
type User = { name: string; age: number };
type PrefixedUser = { [K in keyof User as `get${Capitalize}`]: () => User[K] };Solution
Step 1: Analyze key transformation
Keys 'name' and 'age' are capitalized and prefixed with 'get', becoming 'getName' and 'getAge'.Step 2: Analyze value transformation
Values become functions returning the original property types: () => string and () => number.Final Answer:
{ getName: () => string; getAge: () => number } -> Option DQuick Check:
Mapped keys capitalized + function values = { getName: () => string; getAge: () => number } [OK]
- Not capitalizing keys
- Returning values instead of functions
- Using original keys without prefix
Identify the error in this mapped type using template literals:
type Flags = { isActive: boolean; isAdmin: boolean };
type PrefixedFlags = { [K in keyof Flags as `flag_${K}`]: Flags[K] };Solution
Step 1: Check key remapping syntax
Template literal keys must intersect K with string:string & Kto ensure keys are strings.Step 2: Identify missing intersection
The code uses`flag_${K}`withoutstring & K, causing a type error.Final Answer:
Missing string intersection with K in template literal -> Option CQuick Check:
Usestring & Kin template literals to fix error [OK]
- Omitting string & K intersection
- Thinking Capitalize is mandatory
- Believing template literals can't be used here
Given this type, how would you create a mapped type that prefixes keys with on and capitalizes them, but only for keys starting with handle?
type Handlers = { handleClick: () => void; handleHover: () => void; reset: () => void };Solution
Step 1: Filter keys starting with 'handle'
Use conditional typeK extends `handle${string}`to select only keys starting with 'handle'.Step 2: Rename keys with 'on' prefix and capitalize
Use template literal`on${Capitalize}`to rename keys accordingly.Step 3: Assign original value types
Keep the original function types fromHandlers[K].Final Answer:
type Prefixed = { [K in keyof Handlers as K extends `handle${string}` ? `on${Capitalize}` : never]: Handlers[K] }; -> Option AQuick Check:
Conditional key remapping with prefix and capitalize = type Prefixed = { [K in keyof Handlers as K extends `handle${string}` ? `on${Capitalize}` : never]: Handlers[K] }; [OK]
- Not filtering keys by prefix
- Applying rename to all keys
- Incorrect conditional syntax
Ready to prove it?
Pass the test and this pattern moves unknown
