作为参考,我正在尝试解析定义类型/定义类型#29312。
下面的代码会导致错误,但不应该。
declare const $: JQueryStatic;
let value: string | HTMLElement = {} as any;
$(value);Argument of type 'string | HTMLElement' is not assignable to parameter of type 'PlainObject<any>'.
Type 'string' is not assignable to type 'PlainObject<any>'.JQueryStatic的调用签名当前定义为:
interface JQueryStatic {
<TElement extends HTMLElement = HTMLElement>(html: string, ownerDocument_attributes?: Document | JQuery.PlainObject): JQuery<TElement>;
<TElement extends Element = HTMLElement>(selector: string, context?: Element | Document | JQuery): JQuery<TElement>;
<T extends Element>(element: T): JQuery<T>;
<T extends Element>(elementArray: T[]): JQuery<T>;
<T>(selection: JQuery<T>): JQuery<T>;
<TElement = HTMLElement>(callback: ((this: Document, $: JQueryStatic) => void)): JQuery<TElement>;
<T extends JQuery.PlainObject>(object: T): JQuery<T>;
<TElement = HTMLElement>(): JQuery<TElement>;
}
interface JQuery<T = HTMLElement> {
jquery: string;
}
declare namespace JQuery {
type PlainObject<T = any> = { [name: string]: T; };
}string和HTMLElement有单独的重载,它们可以与之匹配,但不能作为一个联合。这个场景中的解决方案是统一签名。我尝试了以下几点:
interface JQueryStatic2 {
// This solution doesn't entirely fulfill the original requirements but
// seems like a good starting point.
<TElement extends HTMLElement = never,
JElement = never,
T extends JQuery.PlainObject = never>(
arg: string |
TElement |
TElement[] |
JQuery<JElement> |
((this: Document, $: JQueryStatic) => void) |
T
): JQuery<TElement | JElement | T>;
}Argument of type 'string | HTMLElement' is not assignable to parameter of type 'string | ((this: Document, $: JQueryStatic) => void) | JQuery<never> | never[]'.
Type 'HTMLElement' is not assignable to type 'string | ((this: Document, $: JQueryStatic) => void) | JQuery<never> | never[]'.
Type 'HTMLElement' is not assignable to type 'never[]'.
Property 'length' is missing in type 'HTMLElement'.我希望这与TElement = HTMLElement、JElement = never和T = never相匹配。相反,TElement | T似乎被从工会中淘汰了。
我猜想这可以用条件类型来解决,但是@types/jquery目前的目标是TypeScript 2.3,所以我更喜欢不使用新特性来保持兼容性的解决方案。
发布于 2018-10-14 13:57:30
我求助于使用条件类型(需要TypeScript 2.8)。
interface JQueryStatic {
<TDeclared = JQuery._Unknown,
T extends string | Element[] | JQuery<any> | Element | JQuery.PlainObject =
string | Element[] | JQuery<any> | Element | JQuery.PlainObject,
TReturn =
TDeclared extends JQuery._Unknown ?
T extends string ? HTMLElement :
T extends Element[] | JQuery<any> ? T[number] :
T extends Element | JQuery.PlainObject ? T :
never :
TDeclared>(html_selector_element_elementArray_object_selection: T): JQuery<TReturn>;
}
namespace JQuery {
interface _Unknown {
__unknown: never;
}
}这统一了许多原始签名,但却使现在的TDeclared不再受约束。T表示参数的类型,并受限于原始签名的可能类型。如果声明了TReturn (即与哨兵类型JQuery._Unknown不兼容),则它等于TDeclared,否则,将根据T类型推断它。由于T的声明方式,never分支应该是不可访问的。
https://stackoverflow.com/questions/52650182
复制相似问题