-
Notifications
You must be signed in to change notification settings - Fork 1k
[@labs/task] add render return value #2821
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
Conversation
🦋 Changeset detectedLatest commit: c34e532 The changes in this PR will be included in the next version bump. Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
📊 Tachometer Benchmark ResultsSummarynop-update
render
update
update-reflect
Resultslit-element-list
render
update
update-reflect
lit-html-kitchen-sink
render
update
nop-update
lit-html-repeat
render
update
lit-html-template-heavy
render
update
reactive-element-list
render
update
update-reflect
|
| super.update(changedProperties); | ||
| this.taskValue = this.task.value ?? this.task.error; | ||
| this.task.render({ | ||
| this.task.render<string, string>({ |
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.
Ideally this could all be inferred from both the task definition and the callbacks. What's preventing that now?
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.
just talked with steve for a bit! and if i understand correctly, i agree :)
uploaded a change that infers types from the StatusRenderer provided by the user
|
this doesn't quite cover all use cases in #2301 |
|
related to: #2301 |
packages/labs/task/src/task.ts
Outdated
| render(renderer: StatusRenderer<R>) { | ||
| render<SR extends StatusRenderer<R, E>>( | ||
| renderer: Partial<SR> | ||
| ): ReturnType<SR[this['status']]> | undefined { |
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 think this is suboptimal but I think I didn't manage better without type assertions. If I understand correctly this means that undefined is always a possible return value even when all 4 functions are defined and don't return undefined
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.
Don't understand though why in your screenshot above this is not the case.
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.
Why do we need the | undefined?
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.
A partial record of callbacks will always return | undefined as a possible type. If it were a partial record of numbers it'd be the same: number | undefined
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.
Actually if that's true than we don't need it
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.
And there we go, we don't need it. Updated.
packages/labs/task/src/task.ts
Outdated
| PENDING: 1, | ||
| COMPLETE: 2, | ||
| ERROR: 3, | ||
| INITIAL: 'initial', |
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.
Please add a comment that the strings are important as they are used for typing.
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.
sounds good! done!
packages/labs/task/src/task.ts
Outdated
| render(renderer: StatusRenderer<R>) { | ||
| render<SR extends StatusRenderer<R, E>>( | ||
| renderer: Partial<SR> | ||
| ): ReturnType<SR[this['status']]> | undefined { |
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.
Why do we need the | undefined?
packages/labs/task/src/task.ts
Outdated
| complete?: (value: R) => unknown; | ||
| error?: (error: unknown) => unknown; | ||
| // eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
| export type StatusRenderer<R, E, I = any, P = any, C = any, ER = 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.
Why do we need types for I, P, C, ER. Isn't the idea that we're inferring them?
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.
The i, P, C, ER is to hint to the TS compiler that these values should be infered.
The default value of any is so a type inference is not made at first, they could be any type.
When return values for StatusRenderer have a value of unknown then an unknown type is cast and anything that extends StatusRenderer will also have an unknown return type
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.
Heres a small demo of that behavior in action.
In the demo below, the function can't infer a type from values set as unknown. However in can infer types on values with a default of any
[edit, need a second take on the demo]
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.
Here's an example of the slight difference between any and unknown when type inferencing.
Extending an interface with an unknown type actually casts a type of unknown and it needs to be reduced later somehow.
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.
@justinfagnani maybe you might know of a more ergonomic way to pull types out of an interface supplied by a client?
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.
opted to use casting over any for type inference.
|
removed use of type inference with |
| */ | ||
| // eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
| export class Task<T extends [...unknown[]] = any, R = any> { | ||
| export class Task<T extends unknown[] = any, R = any, E = 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.
Since you're casting all instances of E to as E, do you even need E on Task? can't _error simply just be Error and StatusRenderer<R, E> be StatusRenderer<R, E extends Error = Error>?
|
Superseded by #4008 |
Return value is requested to be typed
The types could be inferred from a
StatusRenderRelated to: #2301