-
Notifications
You must be signed in to change notification settings - Fork 467
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add generics to get/query methods #615
Comments
Hi @nstepien, Interestingly, when Testing Library was released, it only supported the |
@kentcdodds I might have not made myself clear, sorry. |
Ah, gotcha. There's currently an effort to migrate this project to TypeScript and maybe when that's finished we can address this. It definitely makes sense. |
@kentcdodds, @nstepien is referring purely to the typescript annotations. If I check the ones that are now at definitely typed, they indeed do not support generics. I'm with @nstepien here, generics would be definitely helpful. It's a way to hint typescript about the return type of the function. Instead of casting it to a given one afterward. // hinting / declaring
screen.queryByText<HTMLButtonElement>('click me'); // -> HTMLButtonElement | null
// casting
screen.queryByText('click me') as HTMLButtonElement; The first one can return type errors if the resulting element isn't a This same story applies to the other methods, |
Update: See #615 (comment) for current opinion. |
That convinced me to go with generics instead. I wish we had a better mechanism because this still masquerades type casting but it's somewhat safer type casting. |
I think the most appropriate way to supporting generics in here would be to have it extend // ...
export type QueryByBoundAttribute<T extends HTMLElement> = (
container: HTMLElement,
id: Matcher,
options?: MatcherOptions,
) => T | null
// ...
export type GetByBoundAttribute<T extends HTMLElement> = (
container: HTMLElement,
id: Matcher,
options?: MatcherOptions,
) => T
// ... |
I agree with @leomeloxp ‘s solution. Using type casting allows the user to potentially set incorrect types and hit undefined errors at runtime. Heres an example: Using casting // Type is incorrectly HTMLImageElement
const element = screen.queryByTestId(‘some-id-that-doesnt-exist’) as HTMLImageElement;
// We get a runtime error, .src does not exist on element
doSomething(element.src) Using generics // Type is correctly HTMLImageElement | null
const element = screen.queryByTestId<HTMLImageElement>(‘some-id-that-doesnt-exist’);
// Error in your code editor/build step telling you to check if "element" is defined before using it
doSomething(element.src) We could argue that developers can cast thier code by using |
So would using generics. Though arguing is moot since all the points you brought up were already included in the initial description. |
@Daniel-Griffiths did you read the opening post? |
From what I've heard about writing type declarations, using generics only to set the return type without checking or inferring against any other types (such as parameters in an endofunctor) is an antipattern. Assertions/casts would be preferred in this case. |
I don't know what it is you read about it, but you can't validate that your type assertion extends |
With TS 4.1, we could provide type-safety for the export type ExtractElement<
RoleMatcher extends ByRoleMatcher
> = RoleMatcher extends ARIARole
? RoleMatcher extends `button`
? HTMLButtonElement
: RoleMatcher extends `textbox`
? HTMLInputElement | HTMLTextAreaElement
: RoleMatcher extends `checkbox`
? HTMLInputElement
: HTMLElement
: HTMLElement This seems to work in my POC, but I think my current implementation can be refactored a bit. |
@timdeschryver A |
Right 🤦♂️, thanks for the reminder. |
@eps1lon Can we reopen this? While the functions are now generic, the way they're set on the |
@nstepien this issue has been closed. If there are other issue with the latest version please open a new one. |
Describe the feature you'd like:
I know the element type I'm querying, so it'd be beneficial to specify it upfront:
Type assertions are very error prone, so should be avoided:
Suggested implementation:
Describe alternatives you've considered:
You can do already do something similar with for example
querySelector
:Teachability, Documentation, Adoption, Migration Strategy:
The text was updated successfully, but these errors were encountered: