Typescript: Web Animation API `Keyframe` requires all `CSSStyleDeclaration` Keys

Created on 31 Jul 2018  路  13Comments  路  Source: microsoft/TypeScript

There appears to be some unexpected behaviour with the way in which animation Keyframes are now declared in the latest version in lib.dom.d.ts:

interface Keyframe extends Record<keyof CSSStyleDeclaration, string> {
    composite?: CompositeOperation | null;
    easing?: string;
    offset?: number | null;
}

Record<keyof CSSStyleDeclaration, string> is causing TypeScript to expect every possible key in CSSStyleDeclaration to be declared when writing animation keyframes:

el.animate([
    { transform: 'translateX(100px)' },
    { transform: 'translateX(0)' }
]);
Argument of type '{ transform: string; }[]' is not assignable to parameter of type 'Keyframe[] | PropertyIndexedKeyframes'.
  Type '{ transform: string; }[]' is not assignable to type 'Keyframe[]'.
    Type '{ transform: string; }' is not assignable to type 'Keyframe'.
      Property 'left' is missing in type '{ transform: string; }'.

This appears to be fixed if I change [P in K] in type Record to be optional:

type Record<K extends keyof any, T> = {
    [P in K]?: T;
};

See reduced test case and playground link below.

TypeScript Version: 3.1.0-dev.20180728


Search Terms:
keyof optional, keyof, Record, CSSStyleDeclaration, animation

Code

type Rec<K extends keyof any, T> = {
    [P in K]: T;
};

interface Declarations {
    x: string | null;
    y: string | null;
    z: string | null;
}

interface X extends Rec<keyof Declarations, string> {}

const test: X = { x: 'string' };

Expected behavior:
Should not require declaration of y and z properties.

Actual behavior:

Type '{ x: string; }' is not assignable to type 'X'.
  Property 'y' is missing in type '{ x: string; }'.

Playground Link: https://www.typescriptlang.org/play/#src=type%20Rec%3CK%20extends%20keyof%20any%2C%20T%3E%20%3D%20%7B%0D%0A%20%20%20%20%5BP%20in%20K%5D%3A%20T%3B%0D%0A%7D%3B%0D%0A%0D%0Ainterface%20Declarations%20%7B%0D%0A%20%20%20%20x%3A%20string%20%7C%20null%3B%0D%0A%20%20%20%20y%3A%20string%20%7C%20null%3B%0D%0A%20%20%20%20z%3A%20string%20%7C%20null%3B%0D%0A%7D%0D%0A%0D%0Ainterface%20X%20extends%20Rec%3Ckeyof%20Declarations%2C%20string%3E%20%7B%7D%0D%0A%0D%0Aconst%20test%3A%20X%20%3D%20%7B%20x%3A%20'string'%20%7D%3B

Related Issues:
Couldn't find any.

Bug lib.d.ts help wanted

Most helpful comment

Thanks to @DanielRosenwasser https://github.com/Microsoft/TSJS-lib-generator/pull/567 has now been merged! I suppose that means this will be fixed in the next release of TS. Thanks Daniel!

All 13 comments

PRs welcomed. You can find more information about contributing lib.d.ts fixes at https://github.com/Microsoft/TypeScript/blob/master/CONTRIBUTING.md#contributing-libdts-fixes.

A PartialRecord<>-like type seems correct but actually Web Animations does not restrict properties to those defined in CSSStyleDeclaration but also permits properties whose name conforms to <custom-property-name> (see process a keyframe-like object). This applies to both Keyframe and PropertyIndexedKeyframe.

So really it should be something like:

interface Keyframe {
    composite?: CompositeOperation | null;
    easing?: string;
    offset?: number | null;
    [property: string]: string;
}

Unfortunately Typescript doesn't allow index types to conflict with other properties so that won't work. And that's about as far as my TS knowledge goes.

In any case, a PartialRecord<>-like approach would still be a big improvement of the current situation, especially since currently only Chrome supports animating custom properties.

The following seems to work for me:

interface Keyframe {
    composite?: CompositeOperation | null;
    easing?: string;
    offset?: number | null;
    [property: string]: string | number | null;
}

interface PropertyIndexedKeyframes {
    composite?: CompositeOperation | (CompositeOperation | null)[];
    easing?: string | string[];
    offset?: number | (number | null)[];
    [property: string]: string | string[] | number | (number | null)[];
}

Although I should probably update the type of composite too now that the spec replaces null with auto (see https://github.com/w3c/csswg-drafts/commit/ced6b5aac02e0e021001f10e4d63e03456686dad).

Remember that web animations API supports two formats for _keyframes_: array and object which is also broken by new version of TS.

https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Keyframe_Formats

Remember that web animations API supports two formats for keyframes: array and object which is also broken by new version of TS.

Yep, the PR I submitted over in TSJS-lib-generator covers both. (I'm the editor of the Web Animations spec, implementer in Firefox, editor of the linked-to wiki etc. so hopefully I got it right!)

That PR, by the way, is https://github.com/Microsoft/TSJS-lib-generator/pull/567. Once that gets merged and the generated definitions make their way back here, this should be fixed.

Would love to see the above PR merged, we're currently unable to update to TS3.

PRs welcomed.

I'm starting to doubt this. I've tried pinging everyone I know at MS to get the PR merged but after 6 weeks I've yet to get any kind of response. In the meantime TS 3.1 has been released and if only someone was available to press the green button it could have fixed this regression.

At the moment TS 3.X is broken for me. My project have to stay with 2.X series because of this regression.

@andy-ms Can you take a look at this and pass on @birtles's PR to the proper set of eyes (https://github.com/Microsoft/TSJS-lib-generator/pull/567)? This issue doesn't seem to be getting any attention and it prevents updating.

We're also blocked by this on FAST-DNA

Thanks to @DanielRosenwasser https://github.com/Microsoft/TSJS-lib-generator/pull/567 has now been merged! I suppose that means this will be fixed in the next release of TS. Thanks Daniel!

Not sure exactly what release this was fixed in, but it's definitely fixed in 4.0. 馃槃

Was this page helpful?
0 / 5 - 0 ratings

Related issues

uber5001 picture uber5001  路  3Comments

kyasbal-1994 picture kyasbal-1994  路  3Comments

DanielRosenwasser picture DanielRosenwasser  路  3Comments

siddjain picture siddjain  路  3Comments

Zlatkovsky picture Zlatkovsky  路  3Comments