如何在TypeScript中使用lodash.mixin

时间:2015-02-25 17:38:26

标签: typescript lodash

我的团队正在评估从JavaScript中将部分文件切换为TypeScript,并且我们在代码中广泛使用了一些自定义mixin方法。从做一些基本的测试看来,虽然我们可以使用_.mixin按照规范创建mixins,但是我们不能在没有编译错误的情况下引用它们。当然,我们可以将这些引用放在定义文件中,但我通常不想修改它。

有什么办法可以做我们正在寻找的东西,还是我们运气不好?

5 个答案:

答案 0 :(得分:4)

你可以这样做。

// somewhere in your project
declare module _ {
    interface LoDashStatic {
        foo(value: string): number;
    }
}

// extend it somewhere else 
declare module _ {
    interface LoDashStatic {
        bar(value: number);
    }
}

Test it out

答案 1 :(得分:3)

请参阅extending built-in types上的TypeScript文档,我认为此处也适用。 _定义为var _: _.LoDashStaticvar s目前无法扩展。

我发现公开扩展的最佳方式是通过lodash-mixins.ts脚本定义新的LoDashMixins接口(扩展LoDashStatic),应用mixins并导出{{1}强制转换为自定义界面。这个例子定义了一个mixin,但想法是将所有mixin添加到一个脚本中以便于导入。

_

如果您想使用mixins,请导入import * as _ from 'lodash'; import xdiff from './xdiff'; interface LoDashMixins extends _.LoDashStatic { xdiff<T>(array:T[], values:T[]): T[]; } _.mixin({xdiff:xdiff}); export default <LoDashMixins>_; 而不是'./lodash-mixins'。现在,您可以对所有内置函数以及mixin进行编译时可见性。

'lodash'

答案 2 :(得分:1)

您可以使用类型擦除来执行此操作:

import _ = require('lodash');

_.mixin(require('lodash-deep'));

function deepSet(lodash: any, path: Array<string>, record: IFooRecord, 
        replacement: number): void { 
    lodash.deepSet(object, path, replacement); 
}

interface IBarRecord {
   bar: number;
}

interface IFooRecord {
   foo: IBarRecord;
}

var subject: IFooRecord = { 
   foo: {
      bar: 0
   }
};
var replacement: number = 1;

deepSet(_, ['foo', 'bar'], subject, replacement);

这是一种混乱,但你的代码会编译。您还可以创建自己的代理,实现mixin的接口,并将lodash模块实例注入其中,以实现更模块化的结果:

import _ = require('lodash');

_.mixin(require('lodash-deep'));    

module 'lodash-deep' {

   export class lodashDeep {

     private _: any;

      constructor(lodash?: any) {
         if (!lodash) {
            lodash = _;
         }
         this._ = lodash;
      }

      public deepSet(collection: any, path: any, value: any): void {
         this._.deepSet(collection, path, value);
      }

      ...

   }

}

答案 3 :(得分:1)

现在,看起来我想要的东西没有任何痛苦。相反,我必须修改lodash.d.ts文件以包含我想要的定义,类似于以下内容:

declare module _ {
    // Default methods declared here...

    //*************************************************************************
    // START OF MIXINS, THESE ARE NOT PART OF LODASH ITSELF BUT CREATED BY US!
    //*************************************************************************

    interface LoDashStatic {
        isNonEmptyString: (str: string) => boolean;
        isEmptyString: (str: string) => boolean;
        isEmptyArray: (a: any[]) => boolean;
        isNonEmptyArray: (a: any[]) => boolean;
        isNullOrEmptyString: (str: string) => boolean;
        isNullOrUndefined: (val: any) => boolean;
        isNullOrEmpty(value: any[]): boolean;
        isNullOrEmpty(value: _.Dictionary<any>): boolean;
        isNullOrEmpty(value: string): boolean;
        isNullOrEmpty(value: any): boolean;
    }

    //*************************************************************************
    // END OF MIXINS
    //*************************************************************************

    // Default types declared here...
}

我讨厌修改默认文件,但它似乎是邪恶中的较小者。

答案 4 :(得分:1)

我发现module augmentation上的文档很有帮助。我结合使用了这个和另一个答案。

// my-lodash.ts
import * as _ from 'lodash';

declare module 'lodash' {
  interface LoDashStatic {
    isNonEmptyString(str: string): boolean;
    isEmptyString(str: string): boolean;
    isEmptyArray<T>(a: T[]): boolean;
    isNonEmptyArray<T>(a: T[]): boolean;
    isNullOrEmptyString(str: string): boolean;
    isNullOrUndefined<T>(val: T): boolean;
    isNullOrEmpty<T>(value: T[]): boolean;
    isNullOrEmpty<T>(value: Dictionary<T>): boolean;
    isNullOrEmpty<T>(value: T): boolean;
  }
}

module LoDash {
  export function isEmptyArray<T>(a: T): boolean {
    return Array.isArray(a) && !a.length;
  }
  // the rest of your functions
}

_.mixin(Object.keys(LoDash)
               .reduce(
                 (object, key) => {
                   object[key] = LoDash[key];
                   return object;
                 },
                 Object.create(null)
              )); 

export = _;

这样做,您可以避免转换或使用默认导出,这意味着您可以以相同的方式继续导入。

现在,在其他一些文件中,请使用增强模块:

// another-file.ts
import * as _ from './my-lodash';

_.isEmptyArray([]);
=> true