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!
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…