typescript - Typede ruter med objektparametere på nye Expo-Router v2
Jeg flytter appen min fra react-navigation til expo-router, men jeg har ennå ikke funnet en løsning for typede ruter.
Jeg vet at det finnes en funksjon som automatisk skriver rutene dine basert på filenes ruter og dynamiske ruter som [slug].tsx.
Men hva om min parameter er et objekt som { id, description, name, age }, hvordan kommer typene til å fungere? Hva bør navnet på filen min være?
Vennligst hjelp! :)
Jeg vil at push eller href fra <Link> skal være typet med parametere og rutenavn
router.push({
pathname: 'home',
params: {
id: 1,
description: '',
age: 1,
name: ''
}
})
motta det riktig også ved useLocalSearchParams()
const Home = () => {
const { id, description, age, name } = useLocalSearchParams();
return <></>
}
Svar #1
Hooken useLocalSearchParams() lar deg angi typen på returverdien, noe som bør være tilstrekkelig så lenge du er sikker på at søkeparametrene dine leveres med riktige verdier.
Så med henvisning til eksemplet ditt tror jeg du kan gjøre følgende:
type SearchParamType = {
id: number;
description: string;
age: number;
name: string;
};
const Home = () => {
const { id, description, age, name } = useLocalSearchParams<SearchParamType>();
return <></>
}
Svar #2
Jeg bruker noe slikt, ikke særlig stolt av det, men det gjør jobben. Ikke godt testet, trenger sannsynligvis noen rettelser og justeringer avhengig av ditt brukstilfelle:
function useSearchParamsTyped<
T extends Record<string, 'string' | 'number' | 'string[]' | 'number[]'>,
>(
params: T,
): {
[K in keyof T]: T[K] extends 'string'
? string
: T[K] extends 'number'
? number
: T[K] extends 'string[]'
? string[]
: T[K] extends 'number[]'
? number[]
: never
} {
const searchParams = useSearchParams()
const result = {} as any
for (const key in params) {
if (params[key] === `string`) {
if (typeof searchParams[key] !== `string`)
throw new Error(`Invalid type for '${key}': '${params[key]}'`)
result[key] = searchParams[key]?.toString()
} else if (params[key] === `number`) {
if (Number.isNaN(Number(searchParams[key])))
throw new Error(`Invalid type for '${key}': '${params[key]}'`)
result[key] = Number(searchParams[key])
} else if (params[key] === `string[]`) {
if (!Array.isArray(searchParams[key]))
throw new Error(`Invalid type for '${key}': '${params[key]}'`)
result[key] = searchParams[key]
} else if (params[key] === `number[]`) {
if (!Array.isArray(searchParams[key]))
throw new Error(`Invalid type for '${key}': '${params[key]}'`)
result[key] = (searchParams[key] as Array<string>).map(Number)
} else {
throw new Error(`Invalid type ${params[key]}`)
}
}
return result
}
