Imagine a scenario where there is a library that exposes a `run` function as shown below:
runner.ts
export type Parameters = { [key: string]: string };
type runner = (args: Parameters) => void;
export default function run(fn: runner, params: Parameters) {
fn(params);
}
Now, consider the code snippet in another file:
index.ts
import type { Parameters } from "./runner.ts";
import run from "./runner.ts";
type CustomParams = { hello: string };
function logGenericArgs(args: Parameters): void {
console.log(args);
}
function logHelloFromArgs(args: CustomParams): void {
console.log(args.hello);
}
run(logGenericArgs, { abc: "123" });
run(logHelloFromArgs, { hello: "123" }); /* TypeScript errors occur due to types being incompatible.
It appears that the 'hello' key in 'CustomParams' does not match the signature of 'Parameters'.
*/
Why does TypeScript raise an issue about the mismatched types, even though they seem compatible? The `Parameters` type signifies a generic object with string keys and values, while `CustomParams` includes a "hello" key that aligns with the structure defined by `Parameters`.
Is there a way to modify the "runner" library's code so that it can accept varying object types and seamlessly interact with them? I prefer not to resort to using 'unknown' or 'any', as they offer limited utility. My goal is for the `run` function's declaration to signify that `args` is an object without restricting it solely to that specific structure. Additionally, I want to refrain from marking the 'hello' key in 'CustomParams' as optional, as it should be mandatory when utilizing the `CustomParams` type, and I do not wish to include 'hello' in the `Parameters` type as it may not be necessary in every usage scenario associated with the "runner" library.