首页 > 解决方案 > TypeScript 打字:Object.defineProperty 函数参数

问题描述

我在这里检查了所有建议的答案,包括:

在 Typescript 中,Object.prototype 函数可以返回子类型实例吗?

但是,无法弄清楚,所以请让我提出新问题。

基本上,我尝试在 JavaScript/TypeScript 中模拟 Infix 表示法进行函数式编程。

这是一个非常肮脏的hack,代码如下:

  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

显然这会发生原型污染。尽管它不在主题范围内,但如果您知道避免该问题的更好方法,请告诉我。

问题是,我想使用 TypeScript 类型检查,如下所示:

customOperator('+')
   ((a: number) => (b: number) => a + b);

不幸的是,在 TypeScript 中,类型检查失败并且没有检测到错误:

console.log(
    "foo"['+'](1)
); // "foo1"

console.log(
    1['+']("bar")
); // "1bar"

让它表现的正确方法是什么?

打字稿 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
  }
}


解决了

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!!

tsconfig.json

{
  "compilerOptions": {
    "target": "es6",
    "module": "esnext",
    "moduleResolution": "node",
    "lib": [
      "esnext",
      "dom"
    ],
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "declaration": false
  }
}

标签: javascripttypescript

解决方案


由于您正在做的事情的性质,我不知道是否有任何“正确”的方法可以做到这一点,但这是您想要做的吗?

interface Number {
  '+'(a: number): number;
}

推荐阅读