You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Expo Router Link类型错误:'/sign-in'不兼容Href<string | object>类型

Expo Router Link组件href类型不匹配错误解决

在Expo项目中集成Clerk身份验证时,按文档完成配置后,Link组件的href属性抛出TypeScript类型错误:

Type '/sign-in' is not assignable to type 'Href<string | object>'.ts(2322)
Link.d.ts(55, 5): The expected type comes from property 'href' which is declared here on type 'IntrinsicAttributes & LinkProps<string | object> & { children?: ReactNode; }'
(property) LinkProps<string | object>.href: Href<string | object>
Path to route to.

错误出现在app/(home)/index.tsx的Link组件中,相关代码文件如下:

app/_layout.tsx

import FontAwesome from '@expo/vector-icons/FontAwesome';
import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native';
import { useFonts } from 'expo-font';
import { Stack, Slot } from 'expo-router';
import * as SplashScreen from 'expo-splash-screen';
import { useEffect } from 'react';
import 'react-native-reanimated';
import { useColorScheme } from '@/components/useColorScheme';

import * as SecureStore from 'expo-secure-store'
import { ClerkProvider, ClerkLoaded } from '@clerk/clerk-expo'

const tokenCache = {
  async getToken(key: string) {
    try {
      const item = await SecureStore.getItemAsync(key)
      if (item) {
        console.log(`${key} was used 🔐 \n`)
      } else {
        console.log('No values stored under key: ' + key)
      }
      return item
    } catch (error) {
      console.error('SecureStore get item error: ', error)
      await SecureStore.deleteItemAsync(key)
      return null
    }
  },
  async saveToken(key: string, value: string) {
    try {
      return SecureStore.setItemAsync(key, value)
    } catch (err) {
      return
    }
  },
}

const publishableKey = process.env.EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY!

if (!publishableKey) {
  throw new Error(
    'Missing Publishable Key. Please set EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY in your .env',
  )
}

export {
  // Catch any errors thrown by the Layout component.
  ErrorBoundary,
} from 'expo-router';

export const unstable_settings = {
  // Ensure that reloading on `/modal` keeps a back button present.
  initialRouteName: '',
};

// Prevent the splash screen from auto-hiding before asset loading is complete.
SplashScreen.preventAutoHideAsync();

export default function RootLayout() {
  const [loaded, error] = useFonts({
    SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'),
    ...FontAwesome.font,
  });

  // Expo Router uses Error Boundaries to catch errors in the navigation tree.
  useEffect(() => {
    if (error) throw error;
  }, [error]);

  useEffect(() => {
    if (loaded) {
      SplashScreen.hideAsync();
    }
  }, [loaded]);

  if (!loaded) {
    return null;
  }

  return <RootLayoutNav />;
}

function RootLayoutNav() {
  const colorScheme = useColorScheme();

  return (
    <ClerkProvider tokenCache={tokenCache} publishableKey={publishableKey}>
    <ClerkLoaded>    
        <Slot />
    </ClerkLoaded>
  </ClerkProvider>
  );
}

app/(auth)/_layout.tsx

import { Redirect, Stack } from 'expo-router'
import { useAuth } from '@clerk/clerk-expo'

export default function AuthRoutesLayout() {
  const { isSignedIn } = useAuth()

  if (isSignedIn) {
    return <Redirect href={'/'} />
  }

  return <Stack />
}

app/(home)/index.tsx(错误源文件)

import { SignedIn, SignedOut, useUser } from '@clerk/clerk-expo'
import { Link } from 'expo-router'
import { Text, View } from 'react-native'

export default function Page() {
  const { user } = useUser()

  return (
    <View>
      <SignedIn>
        <Text>Hello {user?.emailAddresses[0].emailAddress}</Text>
      </SignedIn>
      <SignedOut>
        <Link href="/sign-in">
          <Text>Sign In</Text>
        </Link>
        <Link href="/sign-up">
          <Text>Sign Up</Text>
        </Link>
      </SignedOut>
    </View>
  )
}

解决步骤

  1. 确认对应路由页面存在
    Expo Router的Href类型会自动根据项目中的路由文件生成,若app/(auth)目录下没有sign-in.tsx和sign-up.tsx文件,TypeScript无法识别这些路由路径。创建这两个页面:

    app/(auth)/sign-in.tsx

    import { SignIn } from '@clerk/clerk-expo';
    
    export default function SignInPage() {
      return <SignIn />;
    }
    

    app/(auth)/sign-up.tsx

    import { SignUp } from '@clerk/clerk-expo';
    
    export default function SignUpPage() {
      return <SignUp />;
    }
    
  2. 重启TypeScript服务
    路由文件创建后,VS Code的TypeScript服务可能未自动更新类型。按Ctrl+Shift+P(Windows)或Cmd+Shift+P(Mac),选择「TypeScript: Restart TS Server」,让Expo Router重新生成路由类型定义。

  3. 检查tsconfig.json配置
    确保项目的tsconfig.json包含Expo Router所需的配置,避免类型解析异常:

    {
      "extends": "expo/tsconfig.base",
      "compilerOptions": {
        "strict": true,
        "paths": {
          "@/*": ["./*"]
        }
      },
      "include": ["**/*.ts", "**/*.tsx", ".expo/types/**/*.ts", "expo-env.d.ts"]
    }
    

完成以上步骤后,Link组件的href类型错误应该会消失。

内容的提问来源于stack exchange,提问作者Ash Gharibyan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 20:54:56