首页 > 解决方案 > 如何向我的定制 Javascript 界面添加可选属性?

问题描述

我正在寻找一种在纯 J​​avaScript 中以某种方式使用TypeScript接口的方法,这就是我制作JSInterface的原因。它的代码如下:

function JSInterface() {

  var required = {}

   function _escape(obj) {
     return new Function(' "use strict"; return (' + obj + ')')()
   }

  function _isEqual(x, y) {
     return (x && y && typeof x === 'object' && typeof y === 'object') ?
(Object.keys(x).length === Object.keys(y).length) &&
 Object.keys(x).reduce(function(isEqual, key) {
     return isEqual && _isEqual(x[key], y[key]);
     }, true) : (x === y);
  }

  function _type(obj) {
    return Object.fromEntries(
     Object.entries(obj).map(([k, v]) => {
        var type;
        switch (true) {
           case Array.isArray(v):
              type = "array";
              break;
           case v === null:
              type = "null";
              break;
        default:
              type = typeof v;
      }
     return [k, type];
  })
 );
}

 this.register = function(id, app) {
   Object.assign(required, _escape("{" + id.trim() + ":" + JSON.stringify(app) + "}"))
 }

 this.check = function(id, app) {
  if(_isEqual(required[id], _type(app))) {
    return app
  } else {
   console.log("JSInterface Error")
   return undefined
  }
}

}

用法很简单!下面给出一个例子:

var i = new JSInterface()

// Registering an interface
i.register("i1", {
 one: "string",
 two: "number"
})

// Declaring
var test = {
 two: 23,
 one: "Hello"
}

// Checking 
console.log(
 i.check("i1", test).one, 
 i.check("i1", test).two
)

输出是:

 // => Hello
// => 23

如果,我试图违反接口,例如:

var test {
  two: "23",
  one: "Hello"
}

它返回未定义并在控制台中记录“JSinterface Error”。所以,我对结果很满意,但真正的问题来了,即严格性!接口严格匹配,即如果缺少一个属性,则会产生错误,但我想向 JSInterface 引入可选道具但我不明白该怎么做!所以,你能建议我吗,怎么能做到这一点。我会欣赏一些例子。我知道 javascript 是一种动态类型的语言,但我想在我用 javascript 编码的方式上带来一些严格性,但在一定条件下,即它应该易于使用且灵活使用。例如语法(可能):

i.register("i2", {
 one: "string",
 two: "number" // These props are required
}, {
 three: "object",
 four: "function" // These props are optional 
})

此外,我的方法值得吗?

标签: javascriptobjectinterface

解决方案


我会对此发表评论,但无法输入代码。

您正在拉一根绳子,导致重新创建整个类型系统。但我也这样做了!:)

你可以用任何你想要的方式做到这一点,但这里有一个语法建议:

i.register("i2", {
 one: "string", // Required
 two: "number" // Required
 "three?": "object", // Optional
 "four?": "function" // Optional
})

不过说真的,您正在构建自己的类型系统。这里没有规则。


如果您认为您将做的不仅仅是必需的与可选的,您可能希望允许对象定义您的类型/模型的属性,例如:

i.register("i2", {
 one: "string", // Required
 two: "number" // Required
 three: {
   type: "object",
   required: false,
 },
 four: {
   type: "function",
   required: false,
   readonly: true,
 }
})

推荐阅读