I've taken the code from David Walsh's css animation callback and modified it to TypeScript. However, I'm getting an error and I don't know why:
interface IBrowserPrefix {
[key: string]: string;
}
// http://davidwalsh.name/css-animation-callback
function whichAnimationEvent() {
let x: keyof IBrowserPrefix;
const el = document.createElement('temp');
const browserPrefix: IBrowserPrefix = {
animation: 'animationend',
OAnimation: 'oAnimationEnd',
MozAnimation: 'animationend',
WebkitAnimation: 'webkitAnimationEnd',
};
for (x in browserPrefix) {
if (el.style[x] !== undefined) {
// ^---- [TS Error]: Element has 'any' type b/c index expression is not of type 'number'
return browserPrefix[x];
}
}
}
The error "Element implicitly has 'any' type because index expression is not of type 'number'" occurs when an array is indexed with a value that is not a number. To solve the error, use an object if storing key-value pairs or use a type assertion.
The error "Element implicitly has an 'any' type because expression of type 'string' can't be used to index type" occurs when we use a string to index an object with specific keys. To solve the error, type the string as one of the object's keys.
This is happening because you're attempting to index an object with a numeric index signature with string keys.
for x in browserPrefix
will give you back a set of keys, which are strings. However for some reason CSSStyleDeclaration
has its index type set to number
(and not string
) - see https://github.com/Microsoft/TypeScript/issues/17827.
You're getting this error because you have --noImplicitAny
turned on. A way to get this working (a hacky way) would be to cast the indexer to a string:
for (x in browserPrefix) {
if (el.style[x as any] !== undefined) {
return browserPrefix[x];
}
}
The other way would be to modify the typings (try bumping the issue on github).
while we're here, you should mark x
with const
and if you're going to use for-in on an object you should make sure that the property belongs to the object to avoid pulling in anything that is inherited in the prototype chain:
for (const x in browserPrefix) {
if (browserPrefix.hasOwnProperty(x) && el.style[x as any] !== undefined) {
return browserPrefix[x];
}
}
Alternatively, use for-of
with Object.keys
instead of for-in
.
There's no need to define x
ahead of time here.
There are several problems in the code, the first one is that IBrowserPrefix
is defined as having a string index and thus keyof IBrowserPrefix;
will actually be string. I would remove the interface and just use let x: keyof typeof browserPrefix;
The next problem is the way typescript defined the CSSStyleDeclaration
interface. It only include standard properties, not vendor specific ones.
You could a type assertion to tell the compiler you know what you are doing and ignore the error
export function whichAnimationEvent() {
const el = document.createElement('temp');
const browserPrefix = {
animation: 'animationend',
OAnimation: 'oAnimationEnd',
MozAnimation: 'animationend',
WebkitAnimation: 'webkitAnimationEnd',
};
let x: keyof typeof browserPrefix;
for (x in browserPrefix) {
if (el.style[x as keyof CSSStyleDeclaration] !== undefined) {
return browserPrefix[x];
}
}
}
You could also extend with CSSStyleDeclaration
with the vendor specific keys you require.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With