TypeScript: Unexpected Assignment of Computed Property with Union Type in Object Literal
When working with TypeScript, you might come across a situation where you need to assign a computed property with a union type in an object literal. However, this can sometimes lead to unexpected errors or behavior. In this blog post, we will explore this issue and provide solutions to overcome it.
The Issue
Consider the following code snippet:
interface MyInterface {
prop1: string;
prop2: number;
}
function myFunction(key: keyof MyInterface) {
const obj: { [K in keyof MyInterface]: string | number } = {
[key]: 'value',
};
console.log(obj);
}
myFunction('prop1');
When you try to compile and run this code, you might encounter the following error:
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ prop1: string; prop2: number; }'.
No index signature with a parameter of type 'string' was found on type '{ prop1: string; prop2: number; }'.
This error occurs because TypeScript cannot infer the type of the computed property when using a union type in the object literal. TypeScript expects a specific type for the computed property, but it receives a union type instead.
Solution 1: Type Assertion
One way to overcome this issue is by using a type assertion to explicitly specify the type of the computed property. Here’s an updated code snippet:
interface MyInterface {
prop1: string;
prop2: number;
}
function myFunction(key: keyof MyInterface) {
const obj: { [K in keyof MyInterface]: string | number } = {
[key as keyof MyInterface]: 'value',
};
console.log(obj);
}
myFunction('prop1');
By using the type assertion [key as keyof MyInterface]
, we inform TypeScript about the specific type of the computed property. This allows TypeScript to correctly infer the type and eliminate the error.
Solution 2: Type Guards
Another solution is to use type guards to narrow down the type of the computed property. Here’s an updated code snippet:
interface MyInterface {
prop1: string;
prop2: number;
}
function myFunction(key: keyof MyInterface) {
const obj: { [K in keyof MyInterface]: string | number } = {
[key]: 'value',
};
if (typeof obj[key] === 'string') {
// Handle string type
console.log('String:', obj[key].toUpperCase());
} else {
// Handle number type
console.log('Number:', obj[key].toFixed(2));
}
}
myFunction('prop1');
By using typeof obj[key] === 'string'
as a type guard, we can conditionally handle the different types of the computed property. This allows us to perform specific operations based on the narrowed-down type and avoids any unexpected errors.
Conclusion
When encountering the “Unexpected Assignment of Computed Property with Union Type in Object Literal” issue in TypeScript, you can use type assertions or type guards to overcome it. By explicitly specifying the type or narrowing down the type using conditionals, you can ensure that TypeScript correctly infers the type and eliminates any errors.
Remember to choose the solution that best fits your specific use case. Happy coding!
Leave a Reply