我的团队正在评估从JavaScript中将部分文件切换为TypeScript,并且我们在代码中广泛使用了一些自定义mixin方法。从做一些基本的测试看来,虽然我们可以使用_.mixin按照规范创建mixins,但是我们不能在没有编译错误的情况下引用它们。当然,我们可以将这些引用放在定义文件中,但我通常不想修改它。
有什么办法可以做我们正在寻找的东西,还是我们运气不好?
答案 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);
}
}
答案 1 :(得分:3)
请参阅extending built-in types上的TypeScript文档,我认为此处也适用。 _
定义为var _: _.LoDashStatic
,var
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