-
-
Notifications
You must be signed in to change notification settings - Fork 87
Conversation
It's TBD on whether this will need to be a breaking change or not. I'm converting the Since that'll make maintenance easier, I think I'm OK with supporting Ember 2.4+ or something like that, if it means we can use some of the modern features in Ember. I don't really feel like active 1.13 maintenance is really necessary any more. |
614e22a
to
9268de7
Compare
addon/services/ajax.ts
Outdated
// DO NOT DELETE: this is how TypeScript knows how to look up your services. | ||
declare module '@ember/service' { | ||
interface Registry { | ||
ajax: any; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I couldn't get this right, so I just set it to any
for now.
If I export the service like this instead:
export default class AjaxService extends Service.extend(AjaxRequestMixin);
some of my tests started complaining that I wasn't using new
with the class. I really need to fix this before merging, though, or most people that are looking up the service through an injection won't actually benefit from all the type definitions!
@@ -0,0 +1,12 @@ | |||
import url from 'url'; | |||
|
|||
interface ModuleRegistry { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This bit was kind of weird and hard to figure out, but it allowed me to get around not having types for the FastBoot
global yet.
@Bouke @chriskrycho Would you guys look this over? I tried to add you as reviewers by GitHub won't let me |
I've created a gist with my typings. They might not be fully covering and/or incorrect. I'm also quite new to TypeScript, so there might be better ways to do things. |
addon/mixins/ajax-request.ts
Outdated
*/ | ||
post(url, options) { | ||
post(url: string, options?: AJAXOptions): AJAXPromise<Response> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See my typings where I have generic variants for all the verbs, so for example;
post(url: string, options?: JQuery.AjaxSettings): RSVP.Promise<any>;
post<T>(url: string, options?: JQuery.AjaxSettings): RSVP.Promise<T>;
This allows for clean code on the consumer's side, as the return type is already defined.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense to me, but could you give an example of what that would look like in use? I thought about going that direction with the type definitions, but decided against it because we actually have no way of knowing what the shape actually is.
My guess is that your proposition allows the user to say something like this:
interface User {
name: string;
}
const user = await get<User>(this, 'ajax').get('/users/1');
and allow their application to know that user,name
is a string
, and give the right Intellisense?
My reservation here is that we have no way to know that user
is actually matching the shape of the User
interface; we could tell TypeScript that that's the case, but we have no way to verify it. I think it would actually be safer to keep the AJAXPromise<any>
return type because it's closer to what we can actually guarantee is true about the system.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the other hand, we could take a "user at your own risk" attitude toward the generic type with something like this:
post<T = Response>(url: string, options?: whatever): AjaxPromise<T>
since that would basically tell people that, if left unspecified, the return value is going to resolve to any
. However, if they want to tell the compiler what the type should be treated as, they can -- at their own risk, because they may actually be wrong and cause a runtime error that TypeScript can't help them with.
I think I like this idea best, since it is kind of the "best of both worlds" -- if a user wants to opt into this feature, they can, or else fall back to the original behavior I described, which is arguably safer but might be less helpful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, that's what I did! Thanks for suggesting the generic.
I like the option of having it, if the user is confident in the structure of their JSON response and wants to get the richer experience, but by default it will be of type Response
(which is an alias for any
).
What's nice is that request
and raw
can both be parameterized by a type, even though raw
actually has a return type of AjaxPromise<RawRequest<T>>
. Adding in the generics was fun!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall looks good to me 👍 , however I'm also just beginning to learn TypeScript. As commented elsewhere, adding generics for the verbs would allow the consumer to increase type safety in their code.
cc: @Bouke Thanks for adding your typings! As a fellow TypeScript newb, we can learn some stuff together here! What do you mean, by trying to add a file? I'm not sure what you mean. |
Sorry, must've been the early hour -- I tried to reply to a different issue in a different repository. |
No problem! |
9268de7
to
22ba0af
Compare
22ba0af
to
aca56a2
Compare
aca56a2
to
b268bbd
Compare
Closes #346
Todo