This is a working example.
function doSomething<T extends Record<string, I>, I>({
inputKey = "input",
outputKey = "output",
...rest
}: {
inputKey?: string;
outputKey?: string;
} & T): Record<string, I> {
// Ensure inputKey exists in the input object to prevent runtime errors
if (!(inputKey in rest)) {
throw new Error(`Input key "${inputKey}" not found in input object.`);
}
return {
[outputKey]: rest[inputKey],
};
}
// Example usage:
const result = doSomething({
input: "value",
outputKey: "out",
});
console.log(result);
This doesn't yet infer the type of the result, which is what I'm aiming for.
Wrote up a quick example of how you can do this. You will have to not use ...rest however, as i'd at least have no idea how to infer this well and logically.
type ObjectKeys = symbol | string | number
function getKeyOfObject<InObject extends object, InKey extends keyof InObject, OutKey extends ObjectKeys>
(object: InObject, inKey: InKey, outKey: OutKey)
: { [K in OutKey]: InObject[InKey] } {
return {
[outKey]: object[inKey]
} as any; // Haven't found a way to make the compiler not complain about the result being incorrect
}
const a = getKeyOfObject({ a: 1, b: "test" }, "a", "test")
a.test // number
Explaination:
I don't know the context of how you want to use this. However, unless really necessary I'd reconsider simplifying the function. Currently you are extracting and mapping to a new Object, I can't imagine many scenarios where this would be truly needed. A function for just extracting (with a possible throw) would be simpler to write. Or you could just use the '?' operator to do checked index access.
Small note - this function will not work with nested properties. These require quite a lot more work. I've implemented something for that in a little config library I once made: see https://github.com/Aderinom/typedconf/blob/master/src/config.builder.ts get function in line 99