g-plane / typed-query-selector

Better typed `querySelector` and `querySelectorAll`.
https://www.npmjs.com/package/typed-query-selector
MIT License
729 stars 11 forks source link

Return type parameter in querySelector shim can cause undesired casts #12

Closed brendankenny closed 3 years ago

brendankenny commented 3 years ago

The type parameter E in the querySelector/querySelectorAll shim:

https://github.com/g-plane/typed-query-selector/blob/823e4b850280dab7192cd0468b8e97c196e9e8ec/shim.d.ts#L5-L7

can cause undesired type casts depending on the context of use. The problem is that the type parameter E is used only in the return type. If the context provides a type that extends Element, the compiler will happily use that instead of the default of ParseSelector<S>.

For example:

const anchor: HTMLAnchorElement|null = document.querySelector('div'); // No error.
// querySelector type is `ParentNode.querySelector<"div", HTMLAnchorElement>(selector: "div"): HTMLAnchorElement | null`
const results: Array<HTMLAnchorElement|null> = [];
results.push(document.querySelector('div')); // No error (querySelector type is same as above).

On the other hand, this feature allows the element type overriding feature, like in

document.querySelector<MyComponent>('my-web-component') // ==> MyComponent

so I'm not sure what the best fix would be (if any). It's also easy enough for users of the library to do their own

querySelector<S extends string>(selector: S): ParseSelector<S> | null;

shim if that's their preferred functionality.

g-plane commented 3 years ago

I found that even we put ParseSelector<S> as return type, overriding still works.

g-plane commented 3 years ago

Fixed in v2.4.1 .

864msk commented 3 years ago

معلمة النوع Eفي querySelector/ querySelectorAllshim:

https://github.com/g-plane/typed-query-selector/blob/823e4b850280dab7192cd0468b8e97c196e9e8ec/shim.d.ts#L5-L7

يمكن أن تتسبب في أشكال غير مرغوب فيها من النوع اعتمادًا على سياق الاستخدام. المشكلة هي أن معلمة النوع Eتستخدم فقط في نوع الإرجاع. إذا كان السياق يوفر نوعًا يمتد Element، فسيستخدمه المترجم بسعادة بدلاً من الافتراضي ParseSelector<S>.

على سبيل المثال:

CONST  مرساة : HTMLAnchorElement | خالية  =  وثيقة . querySelector ( 'div' ) ؛  // لا يوجد خطأ. 
// querySelector type هو `ParentNode.querySelector <" div "، HTMLAnchorElement> (المحدد:" div "): HTMLAnchorElement | خالية
 نتائج const : صفيف < HTMLAnchorElement | خالية >  =  [ ] ؛ 
النتائج . push ( document . querySelector ( 'div' ) ) ؛  // لا يوجد خطأ (نوع محدد الاستعلام هو نفسه كما هو مذكور أعلاه).

من ناحية أخرى ، تسمح هذه الميزة لميزة تجاوز نوع العنصر ، كما هو الحال في

وثيقة . querySelector < MyComponent > ( 'my-web-component' )  // ==> MyComponent

لذلك لست متأكدًا من أفضل حل (إن وجد). من السهل أيضًا أن يقوم مستخدمو المكتبة بعمل أعمالهم الخاصة

محدد الاستعلام < S  يوسع السلسلة > ( المحدد : S ) : ParseSelector < S > | لاغية ؛

shim إذا كانت هذه هي وظيفتهم المفضلة.