我在库中使用类似jQuery的初始化模式(我添加了一些有关我希望这些函数接受并返回的类型的注释):
function JQueryConstructor ( selector /*: string | INSTANCE_OF_JQUERY*/ ) {
if ( selector.__jquery ) return selector;
}
function jQuery ( selector/*: string | INSTANCE_OF_JQUERY*/ )/*: INSTANCE_OF_JQUERY*/ {
return new JQueryConstructor ( selector );
}
const fn = jQuery.fn = jQuery.prototype = JQueryConstructor.prototype = {
constructor: jQuery,
__jquery: true
};
fn.foo = function () {};
jQuery ( '*' ).foo; // => Function
const $mocked = { __jquery: true, foo () {} };
jQuery ( $mocked ) === $mocked; // => true
它可以在JavaScript中使用,但是如何在TypeScript中编写它以便正确键入?
我有以下要求/问题:
new Foo ()
的函数返回任意值,而TypeScript则抱怨只能这样调用void函数我找不到解决所有这些问题的方法,您能帮我吗?
答案 0 :(得分:0)
要按顺序解决您的要求/问题:
Typescript
与"declaration": true
选项兼容,我们可以让编译器执行此操作new
调用任何函数或不允许未命中匹配的类型。尽管如果您遇到语义错误,仍然可以发出JS(并且默认情况下编译器会发出),但是建议您修复错误。我想要的解决方案是使用类而不是函数JQueryConstructor
并使用类接口合并来实现可扩展性。结果将类似于:
class JQuery{
__jquery!: boolean; // Just the declaration
constructor(selector: string | JQuery) {
if(typeof selector !== 'string' && selector.__jquery) return selector;
}
}
JQuery.prototype.__jquery = true;
function foo() { };
interface JQuery {
foo: typeof foo
}
JQuery.prototype.foo = foo;
function jQuery(selector: string | JQuery): JQuery {
return new JQuery(selector);
}
jQuery('*').foo; // => Function
const $mocked = { __jquery: true, foo() { } };
jQuery($mocked) === $mocked; // => true
代码的缩小版本(缩小here)与您的代码没有太大区别,您的版本为300bytes,我编译为es2015的版本为261字节,编译为es5的版本为253字节(即使我使用您较长的JQueryConstructor
名称仍为297个字节)。在这么小的示例中比较大小可能完全相关,但似乎具有可比性。
根据上面的代码,将生成以下定义:
declare class JQuery {
__jquery: boolean;
constructor(selector: string | JQuery);
}
declare function foo(): void;
interface JQuery {
foo: typeof foo;
}
declare function jQuery(selector: string | JQuery): JQuery;
declare const $mocked: {
__jquery: boolean;
foo(): void;
};
这将适用于任何使用者,并将允许他们使用相同的类接口合并技术来提供可扩展性。
答案 1 :(得分:0)
由于@ titian-cernicova-dragomir,我想出了以下解决方案,由于必须显式定义所有接口,所以它有些冗长,但可以使用:
interface jQuery {
constructor: typeof jQueryConstructor,
__jquery: boolean
}
function isJQuery ( x ): x is jQuery {
return x && x['__jquery'];
}
function jQuery ( selector: string | jQuery ): jQuery {
if ( isJQuery ( selector ) ) return selector;
return new jQueryConstructor ( selector );
}
function jQueryConstructor ( selector: string ) {}
const fn = jQuery.fn = jQuery.prototype = jQueryConstructor.prototype = {
constructor: jQueryConstructor,
__jquery: true
} as jQuery;
interface jQuery {
foo ();
}
fn.foo = function () {};
jQuery ( '*' ).foo; // => Function
const $mocked = { __jquery: true, foo () {} } as jQuery;
jQuery ( $mocked ) === $mocked; // => true
jQuery ( '*' ) instanceof jQuery; // => true