【问题标题】:How do I generically iterate over the properties of an arbitrary object in TypeScript?如何在 TypeScript 中一般地迭代任意对象的属性?
【发布时间】:2020-01-25 23:46:58
【问题描述】:

这是一个非常常见的 JavaScript 模式:

function mapThruWrapper(module) {
   const replacement = {}

   Object.getOwnPropertyNames(module).forEach(function(key) {
      const val = module[key]

      if (val instanceof Function) {
         replacement[key] = wrapperFunc.bind(null, val)
      } else {
         replacement[key] = val
      }
   })

   return replacement
}

我正在尝试在 TypeScript 中强输入此内容,并且我已经达到了以下内容:

function mapThruWrapper<M extends { [X: string]: unknown }>(module: M): M {
   const replacement: M = {}

   Object.getOwnPropertyNames(module).forEach(function(key) {
      const val = module[key]

      if (val instanceof Function) {
         replacement[key] = wrapperFunc.bind(null, val)
      } else {
         replacement[key] = val
      }
   })

   return replacement
}

不幸的是,这仍然是producing errors 之类的:

src/excmd.ts:186:10 - error TS2322: Type '{}' is not assignable to type 'M'.
  '{}' is assignable to the constraint of type 'M', but 'M' could be instantiated with a different subtype of constraint '{ [X: string]: unknown; }'.

186    const replacement: M = {}
             ~~~~~~~~~~~

src/excmd.ts:192:10 - error TS2536: Type 'string' cannot be used to index type 'M'.

192          replacement[key] = buckleScriptErrorTrampoline.bind(null, $val)
             ~~~~~~~~~~~~~~~~

如何对这样的对象的成员进行强类型泛型迭代和包装?

【问题讨论】:

    标签: typescript types typescript-generics parametric-polymorphism type-variables


    【解决方案1】:

    我对原代码做了一些调整,加了cmets来解释:

    function mapThruWrapper<M extends { [X: string]: unknown }>(module: M): M {
        // Add "as M" so that the compiler allows us to assign an
        // empty object (which is okay since we're populating all the
        // object's properties before the function returns anyway).
        const replacement: M = {} as M
    
        // Use "for in" so that the compiler is able to infer
        // that the variable "key" isn't just a string, but is
        // actually a key in module's type.
        for (const key in module) {
            if (module.hasOwnProperty(key)) {
                const val = module[key]
    
                if (val instanceof Function) {
                    // Use "as typeof val" to let the compiler know that the
                    // bound function has the same signature as the original
                    // function. I'm assuming that's the case here.
                    replacement[key] = wrapperFunc.bind(null, val) as typeof val
                } else {
                    replacement[key] = module[key]
                }
            }
        }
    
        return replacement
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-05-18
      • 1970-01-01
      • 2022-07-14
      • 2011-07-22
      • 1970-01-01
      • 1970-01-01
      • 2019-12-31
      • 1970-01-01
      相关资源
      最近更新 更多