phaserjs / phaserjs/phaser

Add strong typing to `TweenBuilderConfig` callback types

Open
#7,251 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

🐛 TypeScript Bug
Dominant language
JavaScript
Stars
40.3k
Forks
7.2k
PR merge metrics
No merged PRs in 30d

Description

The current type of TweenBuilder looks like this:

type TweenBuilderConfig = {[key: string]: any} & {
    /**
     * The object, or an array of objects, to run the tween on.
     */
    targets: any;
    /**
     * The number of milliseconds to delay before the tween will start.
     */
    delay?: number | Function;
    /**
     * The duration of the tween in milliseconds.
     */
    duration?: number;
    /**
     * The easing equation to use for the tween.
     */
    ease?: string | Function;
    /**
     * Optional easing parameters.
     */
    easeParams?: any[];
    /**
     * The number of milliseconds to hold the tween for before yoyo'ing.
     */
    hold?: number;
    /**
     * The number of times each property tween repeats.
     */
    repeat?: number;
    /**
     * The number of milliseconds to pause before a repeat.
     */
    repeatDelay?: number;
    /**
     * Should the tween complete, then reverse the values incrementally to get back to the starting tween values? The reverse tweening will also take `duration` milliseconds to complete.
     */
    yoyo?: boolean;
    /**
     * Horizontally flip the target of the Tween when it completes (before it yoyos, if set to do so). Only works for targets that support the `flipX` property.
     */
    flipX?: boolean;
    /**
     * Vertically flip the target of the Tween when it completes (before it yoyos, if set to do so). Only works for targets that support the `flipY` property.
     */
    flipY?: boolean;
    /**
     * The time the tween will wait before the onComplete event is dispatched once it has completed, in ms.
     */
    completeDelay?: string | number | Function | object | any[];
    /**
     * The number of times the tween will repeat. (A value of 1 means the tween will play twice, as it repeated once.) The first loop starts after every property in the tween has completed once.
     */
    loop?: string | number | Function | object | any[];
    /**
     * The time the tween will pause before starting either a yoyo or returning to the start for a repeat.
     */
    loopDelay?: string | number | Function | object | any[];
    /**
     * Does the tween start in a paused state (true) or playing (false)?
     */
    paused?: boolean;
    /**
     * The properties to tween.
     */
    props?: {[key: string]:  (number|string|Phaser.Types.Tweens.GetEndCallback|Phaser.Types.Tweens.TweenPropConfig)};
    /**
     * The scope (or context) for all of the callbacks. The default scope is the tween.
     */
    callbackScope?: any;
    /**
     * A function to call when the tween completes.
     */
    onComplete?: Phaser.Types.Tweens.TweenOnCompleteCallback;
    /**
     * Additional parameters to pass to `onComplete`.
     */
    onCompleteParams?: any[];
    /**
     * A function to call each time the tween loops.
     */
    onLoop?: Phaser.Types.Tweens.TweenOnLoopCallback;
    /**
     * Additional parameters to pass to `onLoop`.
     */
    onLoopParams?: any[];
    /**
     * A function to call each time a property tween repeats. Called once per property per target.
     */
    onRepeat?: Phaser.Types.Tweens.TweenOnRepeatCallback;
    /**
     * Additional parameters to pass to `onRepeat`.
     */
    onRepeatParams?: any[];
    /**
     * A function to call when the tween starts playback, after any delays have expired.
     */
    onStart?: Phaser.Types.Tweens.TweenOnStartCallback;
    /**
     * Additional parameters to pass to `onStart`.
     */
    onStartParams?: any[];
    /**
     * A function to call when the tween is stopped.
     */
    onStop?: Phaser.Types.Tweens.TweenOnStopCallback;
    /**
     * Additional parameters to pass to `onStop`.
     */
    onStopParams?: any[];
    /**
     * A function to call each time the tween steps. Called once per property per target.
     */
    onUpdate?: Phaser.Types.Tweens.TweenOnUpdateCallback;
    /**
     * Additional parameters to pass to `onUpdate`.
     */
    onUpdateParams?: any[];
    /**
     * A function to call each time a property tween yoyos. Called once per property per target.
     */
    onYoyo?: Phaser.Types.Tweens.TweenOnYoyoCallback;
    /**
     * Additional parameters to pass to `onYoyo`.
     */
    onYoyoParams?: any[];
    /**
     * A function to call when the tween becomes active within the Tween Manager.
     */
    onActive?: Phaser.Types.Tweens.TweenOnActiveCallback;
    /**
     * Additional parameters to pass to `onActive`.
     */
    onActiveParams?: any[];
    /**
     * A function to call when the tween is paused.
     */
    onPause?: Phaser.Types.Tweens.TweenOnPauseCallback;
    /**
     * Additional parameters to pass to `onPause`.
     */
    onPauseParams?: any[];
    /**
     * A function to call when the tween is resumed after being paused.
     */
    onResume?: Phaser.Types.Tweens.TweenOnResumeCallback;
    /**
     * Additional parameters to pass to `onResume`.
     */
    onResumeParams?: any[];
    /**
     * Will the Tween be automatically destroyed on completion, or retained for future playback?
     */
    persist?: boolean;
    /**
     * The interpolation function to use if the `value` given is an array of numbers.
     */
    interpolation?: string | Function;
};

This:

  • uses a value of any for target, which is unsafe.
  • uses any[] as the type for the "extra parameters" passed to various callbacks (and an any callback scope), which is type-unsafe and has poor heuristics; nothing will stop you from forgetting to pass an extra parameter to a callback (and producing undefined), or expecting target to be a different type as is expected.
  • Numerous uses of Function which provides no information about callback types or return values

In an ideal world, this should be generic on targets and the various callback parameter types.
Unfortunately, TS doesn't really make it easy to parameterize callback types without introducing many many type parameters, so we might need several @template declarations to get the job done.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by locating the TweenBuilderConfig definition and the Phaser.Types.Tweens callback type declarations referenced in the issue. Review how targets, callback scopes, callback parameters, and Function-typed options are currently exposed. Done means the configuration provides stronger target and callback typing without the unsafe any and Function usages described in the issue.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
api
Issue type
Refactor
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.