If you're looking for a solution, something like the following might be your best bet:
export function mapProp<PropertyName extends string, AssignedType>(
value: AssignedType,
propertyName: PropertyName
) {
type ReturnType = {
[K in PropertyName]: AssignedType
};
// similar to Record<PropertyName, AssignedType>
return {
[propertyName]: value
} as ReturnType;
}
In this scenario, utilizing a mapped type instead of an indexed signature is what stands out. By incorporating the generic type parameter PropertyName
, it allows for more specific key narrowing beyond just being a string
:
const thing = mapProp(123, "abc");
thing.abc; // number
thing.def; // error
With this setup, ReturnType
becomes akin to {abc: number}
. However, if only a string
key is known during compilation, the resulting outcome would resemble:
declare const propName: string;
const stuff = mapProp(123, propName);
stuff.abc; // number
stuff.def; // number
At that point, ReturnType
transforms into {[k: string]: number}
, meaning any string
key is accepted while assigning it a number
value. It may not align with your ideal scenario, but given the circumstances, it's the closest option available.
Additionally, note that without resorting to a type assertion (as ReturnType
), computed properties usually default to string indexes rather than anything more precise. This currently reflects a design limitation within TypeScript. While there have been efforts to address this matter (referenced here), no concrete resolution has been implemented into the language yet.
Wishing you all the best with implementing this solution!