I have a collection of functions stored as key-value pairs that can be utilized by a "processor".
const fns = {
foo: () => ({ some: "data", for: "foo" }),
bar: () => ({ and: "data", for: "bar" }),
baz: () => ({ baz: "also", is: "here" }),
};
Next, I define an interface outlining the requirements of a "processor":
interface NeedyProcessor {
needed: Array<keyof typeof fns>;
// Question 1: Can needsMet be typed more strongly?
process: (needsMet: any) => any;
}
The objective is to specify the required function properties from `fns` that the processor needs to operate.
For example, if `needed` includes `["foo"]`, it implies that the `processor` will receive an object `needsMet` with a single property, `foo`, holding the value of `foo` from `fns`.
However, inadequate typing leads to potential errors like the uncaught issue in Typescript:
const broken: NeedyProcessor = {
needed: ["foo", "baz"],
process: (needsMet) => ({
fooResult: needsMet.foo(),
// Question 1 cont: So that this call would give an error in the IDE
barResult: needsMet.bar(), // Runtime error! bar won't exist
bazResult: needsMet.baz(),
}),
};
To illustrate further, here's a scenario without runtime errors:
const working: NeedyProcessor = {
needed: ["bar"],
process: (needsMet) => ({
barResult: needsMet.bar(),
}),
};
A helper function will facilitate making the call. It's crucial to include only the necessary `fns` for `process`:
function callProcessor(spec: NeedyProcessor) {
// Question 2: Could this any be typed more strongly? Not as important as question 1 though
const needsMet: any = {}
spec.needed.forEach(x => needsMet[x] = fns[x])
return spec.process(needsMet);
}
One scenario will succeed while the other fails:
console.log("working", callProcessor(working));
console.log("broken", callProcessor(broken));