motiondivision / motionone

https://motion.dev
MIT License
2.86k stars 52 forks source link

[Bug] BezierDefinition type should be readonly so as const can be used #94

Closed xaviergonz closed 2 years ago

xaviergonz commented 2 years ago

1. Describe the bug

Due to the type of BeizerDefinition

export type BezierDefinition = [number, number, number, number]

The following does not work:

const element = document.querySelector("whatever")!;

// won't work, number[] is not ok (this is expected)
const transition = {
  easing: [1, 2, 3, 4]
};

animate(element, {}, transition);

// won't work, it is readonly but the type expects it to be mutable :(
const transition2 = {
  easing: [1, 2, 3, 4]
} as const;

animate(element, {}, transition2);

since the BeizerDefinition should be readonly.

Additionally, the transitions cannot be strongly typed since the animate argument types are not exported, so I cannot do this:

// won't work, the type AnimationOptionsWithOverrides is not exported
const transition3: AnimationOptionsWithOverrides = {
  easing: [1, 2, 3, 4]
};

animate(element, {}, transition3);

2. IMPORTANT: Provide a CodeSandbox reproduction of the bug

https://codesandbox.io/s/agitated-field-7xdsf9?file=/src/index.ts

3. Steps to reproduce

Ignore the code, just check the TS compilation errors.

4. Expected behavior

I expect the as const method to work, as well as being able to import the types of the arguments to animate if needed.

mattgperry commented 2 years ago

For now you can import type { AnimationOptionsWithOverrides } from "@motionone/dom" but I agree this should be amended, probably with a nicer name.

xaviergonz commented 2 years ago

I think just changing export type BezierDefinition = [number, number, number, number] to export type BezierDefinition = readonly [number, number, number, number] would be a step in the right direction :)

mattgperry commented 2 years ago

I don't think it's that simple - merely changing that results in these errors:

src/utils/easing.ts(21,53): error TS2556: A spread argument must either have a tuple type or be passed to a rest parameter.
src/utils/easing.ts(24,20): error TS2538: Type 'BezierDefinition' cannot be used as an index type.
src/utils/easing.ts(24,53): error TS2538: Type 'BezierDefinition' cannot be used as an index type.
src/utils/easing.ts(27,18): error TS2339: Property 'startsWith' does not exist on type 'Easing'.
Property 'startsWith' does not exist on type 'BezierDefinition'.
src/utils/easing.ts(28,41): error TS2345: Argument of type 'Easing' is not assignable to parameter of type 'string'.
Type 'BezierDefinition' is not assignable to type 'string'.
mattgperry commented 2 years ago

I'll have a look through and see if these can be solved individually though