There appears to be some unexpected behaviour with the way in which animation Keyframe
s 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.
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. 馃槃
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!