diff --git a/src/grid-item/index.js b/src/grid-item/index.tsx
similarity index 84%
rename from src/grid-item/index.js
rename to src/grid-item/index.tsx
index 9b000babb..a3c4a6b15 100644
--- a/src/grid-item/index.js
+++ b/src/grid-item/index.tsx
@@ -1,9 +1,9 @@
-import { computed } from 'vue';
+import { computed, CSSProperties } from 'vue';
 
 // Utils
 import { createNamespace, addUnit } from '../utils';
 import { BORDER } from '../utils/constant';
-import { GRID_KEY } from '../grid';
+import { GRID_KEY, GridProvide } from '../grid';
 
 // Composition
 import { useParent } from '@vant/use';
@@ -26,13 +26,20 @@ export default createComponent({
   },
 
   setup(props, { slots }) {
-    const { parent, index } = useParent(GRID_KEY);
+    const { parent, index } = useParent<GridProvide>(GRID_KEY);
     const route = useRoute();
 
+    if (!parent) {
+      if (process.env.NODE_ENV !== 'production') {
+        console.error('[Vant] GridItem must be a child component of Grid.');
+      }
+      return;
+    }
+
     const rootStyle = computed(() => {
       const { square, gutter, columnNum } = parent.props;
-      const percent = `${100 / columnNum}%`;
-      const style = {
+      const percent = `${100 / +columnNum}%`;
+      const style: CSSProperties = {
         flexBasis: percent,
       };
 
@@ -128,10 +135,10 @@ export default createComponent({
       return (
         <div class={[bem({ square })]} style={rootStyle.value}>
           <div
-            role={clickable ? 'button' : null}
+            role={clickable ? 'button' : undefined}
             class={classes}
             style={contentStyle.value}
-            tabindex={clickable ? 0 : null}
+            tabindex={clickable ? 0 : undefined}
             onClick={route}
           >
             {renderContent()}
diff --git a/src/grid/index.js b/src/grid/index.tsx
similarity index 69%
rename from src/grid/index.js
rename to src/grid/index.tsx
index 51218100e..fd20faef3 100644
--- a/src/grid/index.js
+++ b/src/grid/index.tsx
@@ -1,3 +1,4 @@
+import { PropType } from 'vue';
 import { createNamespace, addUnit } from '../utils';
 import { BORDER_TOP } from '../utils/constant';
 import { useChildren } from '@vant/use';
@@ -6,12 +7,27 @@ const [createComponent, bem] = createNamespace('grid');
 
 export const GRID_KEY = 'vanGrid';
 
+export type GridDirection = 'horizontal' | 'vertical';
+
+export type GridProvide = {
+  props: {
+    center: boolean;
+    border: boolean;
+    square?: boolean;
+    gutter?: number | string;
+    iconSize?: number | string;
+    columnNum: number | string;
+    direction?: GridDirection;
+    clickable?: boolean;
+  };
+};
+
 export default createComponent({
   props: {
     square: Boolean,
     gutter: [Number, String],
     iconSize: [Number, String],
-    direction: String,
+    direction: String as PropType<GridDirection>,
     clickable: Boolean,
     columnNum: {
       type: [Number, String],