I think the closest you're going to get is something like this:
export function mapProp<PropertyName extends string, AssignedType>(
value: AssignedType,
propertyName: PropertyName
) {
type ReturnType = {
[K in PropertyName]: AssignedType
};
// equivalent to Record<PropertyName, AssignedType>
return {
[propertyName]: value
} as ReturnType;
}
In this case you'd be using a mapped type instead of a type with an index signature. The addition of the PropertyName generic type parameter allows the narrowing of the key past string, if you pass it a string literal:
const thing = mapProp(123, "abc");
thing.abc; // number
thing.def; // error
In that case ReturnType is known to be equivalent to {abc: number}. If all you know is that the key is a string at compile time, then you get this:
declare const propName: string;
const stuff = mapProp(123, propName);
stuff.abc; // number
stuff.def; // number
Now ReturnType is equivalent to {[k: string]: number}, meaning it accepts any string key (and gives it a number value). This might not be what you want, but it's the best the compiler can do in this case.
Also note that without using a type assertion (as ReturnType), computed properties usually end up as string indexes instead of something more specific. This is currently a design limitation of TypeScript. There have been some attempts to deal with this, but nothing has made it into the language yet.
Hope that helps; good luck!