The issue extends beyond the original question posed by OP.
Consider this scenario where we define an interface and a variable of that interface:
interface IObj {
prop: string;
}
const obj: IObj = { prop: 'string' };
Can we assign obj
to type Record<string, string>
?
The answer is No. Demo
// TS2322: Type 'IObj' is not assignable to type 'Record<string, string>'. Index signature for type 'string' is missing in type 'IObj'.
const record: Record<string, string> = obj;
Why does this happen?
To explain, let's revisit our understanding of "upcasting" and "downcasting", as well as the significance of the "L" letter in SOLID principles.
The following examples do not result in errors because we are assigning a broader type to a more specific one.
Demo
const initialObj = {
title: 'title',
value: 42,
};
interface IObj {
title: string;
}
const obj: IObj = initialObj; // No error here
obj.title;
obj.value; // Property 'value' does not exist on type 'IObj'.(2339)
IObj
only requires one property, so the assignment is valid.
A similar concept applies to Types. Demo
const initialObj = {
title: 'title',
value: 42,
};
type TObj = {
title: string;
}
const obj: TObj = initialObj; // No error here
obj.title;
obj.value; // Property 'value' does not exist on type 'TObj'.(2339)
The absence of errors in the last two examples is due to the concept of "upcasting", where a value type is cast to a higher type (an ancestor entity). You can assign Dog to Animal, but not the other way around (Refer to the meaning of "L" in SOLID principles). Assigning from Dog to Animal represents "upcasting", which is considered a safe operation.
Record<string, string>
is much broader than an object with just one property, as it allows for additional properties.
const fn = (record: Record<string, string>) => {
record.value1;
record.value2;
record.value3; // No errors here
}
Thus, when you attempt to assign the IObj
Interface to Record<string, string>
, an error occurs. The assignment should be made to a type that extends IObj
. The Record<string, string>
type can be a subclass of IObj
.
In other responses, suggestions may include using a Type to resolve the issue. However, this might not be the correct approach, and it's advisable to avoid such constructs.
This issue raises pertinent questions in this context, along with an insightful related comment.