I am looking for a way to dynamically type some values and methods on a class I have.
Example
I'll start simple. This is the behaviour I want. (I think)
const options = ["opt1", "opt2"] as const;
type AdvancedFixedValue = {
[L in typeof options[number]]: number;
};
This lets me know if I have set a property that doesn't exist.
const advancedExample: AdvancedFixedValue = {
opt1: 2,
opt2: 3,
opt3: 3 // This will error
};
The Problem
However rather than options be a defined list, the values will be semi-dynamic (they are not coming from a database or anything). Here is my full implementation.
Activity Class
On the activity class I want to add "fixed values" which is just an object, but want the keys of that object to be checked against the values of the variables on the Equation class.
type BasicFixedValue = {
[key: string]: number;
};
class Activity {
id: string;
equation: Equation;
fixedValues: BasicFixedValue;
constructor() {
this.id = "test";
this.fixedValues = {};
this.equation = new Equation({ variables: ["test"] });
}
public setEquation(equation: Equation): Activity {
this.equation = equation;
return this;
}
public addFixedValues(fixedValues: BasicFixedValue): Activity {
this.fixedValues = {
...this.fixedValues,
...fixedValues
};
return this;
}
}
Equation class
type EquationParams = {
variables?: string[];
};
export class Equation {
id: string;
equation?: string;
variables: string[] = [""];
constructor(params: EquationParams) {
this.id = "test";
this.variables = params?.variables ?? ["hi"];
}
public setEquation(equation: string): Equation {
this.equation = equation;
return this;
}
public addVariable(variables: string[] | string): Equation {
const deDupe = new Set(this.variables);
if (variables instanceof Array) {
variables.forEach((variable) => deDupe.add(variable));
} else {
deDupe.add(variables);
}
this.variables = Array.from(deDupe);
return this;
}
}
Test cases
// Make a new equation with "a" and "b"
const equation1 = new Equation({ variables: ["a", "b"] })
// Add it to the activity
const activity1 = new Activity().setEquation(equation1);
// This should show a typescript error because "test" is not in the variables of the equation added to the activity
activity1.addFixedValues({ c: 20 });
// This should be fine
activity1.addFixedValues({ a: 20 });
// After adding "c" to the equation,
equation1.addVariable("c");
// it should now be fine
activity1.addFixedValues({ c: 20 });