After reviewing all the suggested answers, including:
in Typescript, can Object.prototype function return Sub type instance?
I still couldn't find a solution, so I'm reaching out with a new question.
My goal is to replicate Infix notation in JavaScript/TypeScript for functional programming.
The current approach involves a somewhat unconventional method as shown below:
const customOperator = op => f =>
Object.defineProperty(
Object.prototype, op,
{
value: function (a) {
return f(this)(a)
},
enumerable: false,
configurable: false,
writable: false
});
customOperator('+')
(a => b => a + b);
console.log(
1['+'](2) // <--Infix notation
); //3
It's worth noting that this method leads to prototype pollution. While it might be off-topic, any insights on how to avoid this issue would be appreciated.
The main question is related to TypeScript type checking requirements:
customOperator('+')
((a: number) => (b: number) => a + b);
Currently, the type-checking fails in TypeScript and doesn't flag any errors in scenarios like:
console.log(
"foo"['+'](1)
); // "foo1"
console.log(
1['+']("bar")
); // "1bar"
What would be the correct approach to address this behavior?
TypeScript version used: 3.8.3
tsconfig.json
{
"compilerOptions": {
"target": "es6",
"module": "esnext",
"moduleResolution": "node",
"lib": [
"esnext",
"dom"
],
"outDir": "./dist",
"rootDir": "./src",
"strict": false,
"declaration": false,
"noImplicitThis": true
}
}
SOLVED
const customOperator = (op: string) => (f: Function) =>
Object.defineProperty(
Object.prototype, op,
{
value: function (a: undefined) {
return f(this)(a)
},
enumerable: false,
configurable: false,
writable: false
});
customOperator('+')
((a: number) => (b: number) => a + b);
interface Number {
'+'(a: number): number;
}
console.log(
1['+'](2)
); //no error
console.log(
"foo"['+'](1)
); // type error!!
console.log(
1['+']("bar")
); // type error!!
using
tsconfig.json
{
"compilerOptions": {
"target": "es6",
"module": "esnext",
"moduleResolution": "node",
"lib": [
"esnext",
"dom"
],
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"declaration": false
}
}