Interfaces
IDictionary
Simple TS object type definition for object based arrays (like in JS) but that works with TS.
let myObj: object = {
a: 1,
b: 2,
};
myObj.a; // is 1
myObj["a"]; // would show an error if not using IDictionary since the object does not have an index definition
let myObj: IDictionary<number> = {
a: 1,
b: 2,
};
// So by using IDictionary, we can reference items by their index without the warnings/errors
myObj["a"];
ParamsFromString
Use string interpolation like this, but dynamically in a string.
const var1 = "abc";
console.log(`var is: ${var1}`);
public format(message: string, meta: object) {
// do blah here to format
}
format("this var: {var1}", {
var1: "abc"
});
import { ParamsFromString } from '@bettercorp/tools/lib/Interfaces';
function format<T extends string>(message: T, meta: Record<ParamsFromString<T>, string>) {
// do blah here to format
}
format("this var: {var1}", { var1: "abc" });
format("this var: {var1}", { bad: "abc" }); // type error
// ref: https://stackoverflow.com/a/73394054/8083582
DynamicallyReferencedMethod
Let's say we have an interface to define a class.
That interface looks something like this:
interface myInterface {
func1(): void;
func2(a: string): void;
func3(a: string): boolean;
func4(a: string, b?: number): boolean;
}
And our main class
class myClass implements myInterface {
func1(): void {
return;
};
func2(a: string): void {
return;
};
func3(a: string): boolean {
return true;
};
func4(a: string, b?: number): boolean {
return true;
};
}
Now the whole reason for this type is so we can easily reference methods in myClass
from within a different class from another place and without loading myClass
.
class myOtherClass<T> {
private referenceClass: myClass;
constructor () {
this.referenceClass = new myClass();
}
callFunction<TA extends string> (...args: DynamicallyReferencedMethod<DynamicallyReferencedMethodType<T>, TA>): DynamicallyReferencedMethod<DynamicallyReferencedMethodType<T>,TA, false> {
return (this.referenceClass as DynamicallyReferencedMethodType<myClass>)[args.splice(0,1)[0] as TA](...args);
}
}
So now we can call up our myOtherClass
without loading myClass
.
(In this example, we call it directly, however you could have it send the method request over a wire to myClass
)
let createdClass = new myOtherClass<myInterface>();
console.log(createdClass.callFunction("func3", "Ab")); // outputs false
console.log(createdClass.callFunction("func3", "A")); // outputs true
createdClass.callFunction("func1"); // Would do nothing - but specifically there are no errors thrown
createdClass.callFunction("funcE"); // This function doesn't exist, so typescript throws an error