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> ) }
解决步骤
确认对应路由页面存在
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 />; }重启TypeScript服务
路由文件创建后,VS Code的TypeScript服务可能未自动更新类型。按Ctrl+Shift+P(Windows)或Cmd+Shift+P(Mac),选择「TypeScript: Restart TS Server」,让Expo Router重新生成路由类型定义。检查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
相关产品推荐
相关产品推荐

