diff --git a/packages/utils/deep-assign.js b/packages/utils/deep-assign.ts
similarity index 74%
rename from packages/utils/deep-assign.js
rename to packages/utils/deep-assign.ts
index 75d2f0df0..46ae77077 100644
--- a/packages/utils/deep-assign.js
+++ b/packages/utils/deep-assign.ts
@@ -3,7 +3,11 @@ import { isDef, isObj } from '.';
 
 const { hasOwnProperty } = Object.prototype;
 
-function assignKey(to, from, key) {
+type Object = {
+  [key: string]: any;
+}
+
+function assignKey(to: Object, from: Object, key: string) {
   const val = from[key];
 
   if (!isDef(val) || (hasOwnProperty.call(to, key) && !isDef(to[key]))) {
@@ -17,7 +21,7 @@ function assignKey(to, from, key) {
   }
 }
 
-export default function assign(to, from) {
+export default function assign(to: Object, from: Object) {
   Object.keys(from).forEach(key => {
     assignKey(to, from, key);
   });
diff --git a/packages/utils/scroll.js b/packages/utils/scroll.js
deleted file mode 100644
index bc6ff9e77..000000000
--- a/packages/utils/scroll.js
+++ /dev/null
@@ -1,41 +0,0 @@
-import { isServer } from '.';
-
-export const getComputedStyle = !isServer && document.defaultView.getComputedStyle.bind(document.defaultView);
-
-// get nearest scroll element
-// http://w3help.org/zh-cn/causes/SD9013
-// http://stackoverflow.com/questions/17016740/onscroll-function-is-not-working-for-chrome
-export function getScrollEventTarget(element, rootParent = window) {
-  let node = element;
-  while (
-    node &&
-    node.tagName !== 'HTML' &&
-    node.tagName !== 'BODY' &&
-    node.nodeType === 1 &&
-    node !== rootParent
-  ) {
-    const { overflowY } = getComputedStyle(node);
-    if (overflowY === 'scroll' || overflowY === 'auto') {
-      return node;
-    }
-    node = node.parentNode;
-  }
-  return rootParent;
-}
-
-export function getScrollTop(element) {
-  return 'scrollTop' in element ? element.scrollTop : element.pageYOffset;
-}
-
-export function setScrollTop(element, value) {
-  'scrollTop' in element ? (element.scrollTop = value) : element.scrollTo(element.scrollX, value);
-}
-
-// get distance from element top to page top
-export function getElementTop(element) {
-  return (element === window ? 0 : element.getBoundingClientRect().top) + getScrollTop(window);
-}
-
-export function getVisibleHeight(element) {
-  return element === window ? element.innerHeight : element.getBoundingClientRect().height;
-}
diff --git a/packages/utils/scroll.ts b/packages/utils/scroll.ts
new file mode 100644
index 000000000..2ce9c8b22
--- /dev/null
+++ b/packages/utils/scroll.ts
@@ -0,0 +1,44 @@
+type ScrollElement = HTMLElement | Window;
+
+// get nearest scroll element
+// http://w3help.org/zh-cn/causes/SD9013
+// http://stackoverflow.com/questions/17016740/onscroll-function-is-not-working-for-chrome
+export function getScrollEventTarget(element: HTMLElement, rootParent: ScrollElement = window) {
+  let node = element;
+  while (
+    node &&
+    node.tagName !== 'HTML' &&
+    node.tagName !== 'BODY' &&
+    node.nodeType === 1 &&
+    node !== rootParent
+  ) {
+    const { overflowY } = window.getComputedStyle(node);
+    if (overflowY === 'scroll' || overflowY === 'auto') {
+      return node;
+    }
+    node = <HTMLElement>node.parentNode;
+  }
+  return rootParent;
+}
+
+export function getScrollTop(element: ScrollElement): number {
+  return 'scrollTop' in element ? element.scrollTop : element.pageYOffset;
+}
+
+export function setScrollTop(element: ScrollElement, value: number) {
+  'scrollTop' in element ? (element.scrollTop = value) : element.scrollTo(element.scrollX, value);
+}
+
+// get distance from element top to page top
+export function getElementTop(element: ScrollElement) {
+  return (
+    (element === window ? 0 : (<HTMLElement>element).getBoundingClientRect().top) +
+    getScrollTop(window)
+  );
+}
+
+export function getVisibleHeight(element: ScrollElement) {
+  return element === window
+    ? element.innerHeight
+    : (<HTMLElement>element).getBoundingClientRect().height;
+}