实现思路
- 定义一个泛型函数,泛型参数代表动画数据的类型。
- 在函数内部,根据动画的逻辑对传入的数据进行操作,由于使用了泛型,这些操作在编译时会根据实际传入的数据类型进行类型检查。
- 利用TypeScript的类型推断机制,在调用函数时,编译器会自动根据传入的参数推断出泛型的具体类型,从而保证类型安全。
代码实现
function animate<T>(initialValue: T, endValue: T, duration: number, callback: (value: T) => void) {
const startTime = performance.now();
const step = (timestamp: number) => {
const elapsed = timestamp - startTime;
const progress = Math.min(elapsed / duration, 1);
// 这里假设动画是线性插值,对于对象类型需要更复杂的处理
const interpolatedValue = interpolate(initialValue, endValue, progress);
callback(interpolatedValue);
if (progress < 1) {
requestAnimationFrame(step);
}
};
requestAnimationFrame(step);
}
function interpolate<T>(start: T, end: T, progress: number): T {
if (typeof start === 'number' && typeof end === 'number') {
return (start + (end - start) * progress) as unknown as T;
}
// 处理对象类型,这里简单示例,实际可能需要深度合并等操作
if (typeof start === 'object' && typeof end === 'object' && start !== null && end!== null) {
const result = {} as T;
for (const key in start) {
if (Object.prototype.hasOwnProperty.call(start, key)) {
result[key] = interpolate((start as any)[key], (end as any)[key], progress);
}
}
return result;
}
return start;
}
利用类型系统避免潜在运行时错误
- 泛型参数检查:通过定义泛型
T
,在编译时,TypeScript会检查传入的 initialValue
和 endValue
是否具有相同的类型。如果类型不一致,编译器会报错,避免在运行时出现类型不匹配的错误。
- 函数参数类型检查:
callback
函数的参数类型被定义为 T
,确保回调函数中对动画值的操作是类型安全的。如果回调函数内部对 value
的操作不符合 T
的类型定义,编译器会报错。
- 插值函数类型检查:
interpolate
函数同样使用泛型 T
,在处理不同类型数据的插值时,会根据传入数据的类型进行相应的操作。例如对于数字类型直接进行线性插值,对于对象类型会递归处理属性,确保类型安全。如果插值操作不符合类型定义,编译器会报错,从而避免运行时错误。