reactjs - Hvordan få de faktiske typene på argumentene til en funksjon som sendes til en annen funksjon
Jeg har en tilpasset hook i React som utfører noen side-effekter for å gjøre hentingsforespørsler.
I kjernen aksepterer hooken en hentefunksjon og returnerer en dekorert versjon som kan kalles av komponenten. Når den dekorerte funksjonen kalles, settes responsen til tilstand og returneres også (lignende returstruktur som useState).
Den innsendte hent-funksjonen og den dekorerte funksjonen vil ha nøyaktig de samme parametrene/typene, men returtypen vil være forskjellig.
Problemet jeg har er å legge til typer på både de returnerte tilstandsdataene og den returnerte dekorerte funksjonen. Jeg ser ut til å bare få den ene eller den andre til å fungere uten å tvinge brukeren av hooken til å oppgi det jeg mener er dupliserte data.
// Dummy useState for dep-free example
function useState<State>(initial: State): [State, (newState: State) => void] {
return [initial, (newState: State) => {}];
}
function useFetch<Data, FetchParams extends any[]>(
fetchFunction: (...args: FetchParams) => Promise<Response>,
initial_value: Data | null = null
): [Data | null, (...args: FetchParams) => Promise<void>] {
const [response, setResponse] = useState<Data | null>(initial_value);
async function wrappedFetch(...args: FetchParams): Promise<void> {
// Side Effects
const res = await fetchFunction(...args);
const result = await res.json();
// Side Effects
if (res.ok) {
setResponse(result);
}
// Side Effects
}
return [
response,
wrappedFetch
];
}
I bruk, hvis du angir typen for den returnerte tilstanden, må du også oppgi typene til parameterne, noe jeg ikke liker. Å bruke Typescripts Parameters gjør dette enkelt, men det føles unødvendig. Denne hooken vil bli brukt hundrevis av ganger i kodebasen, og jeg vil ikke tvinge utviklere til å sende inn det som føles som dupliserte data hver gang.
async function getStuff(value: string): Promise<Response> {
return new Promise((res) => {
res(new Response(value))
})
}
interface SampleData {
value: 'string';
}
const [test, getTest] = useFetch<SampleData, Parameters<typeof getStuff>>(getStuff)
getTest('test'); // Correctly typed, passing nothing or a non-string will error.
Hvis du ikke sender noen typeparametere til useFetch, vil den utlede riktig type for funksjonen, men har ingen måte å vite typen til test på.
Mål
Jeg vil kunne bruke hooken med riktig type tilknyttet både test og getTest, uten å måtte oppgi argumentene - på denne måten:
const [test, getTest] = useFetch<SampleData>(getStuff)
// test = SampleData | null
// getTest = (value: string) => Promise<void>
Hva annet jeg har prøvd
- Bruke
Parametersinne i hooken:
async function wrappedFetch(...args: Parameters<typeof fetchFunction>): Promise<void> {
Men dette ser ut til å bruke standardtypen som er gitt (any[]) i stedet for å være basert på den faktiske funksjonen som ble sendt inn.
- Å gi en standardverdi til
FetchParamsslik at utvikleren kan sende innData-typen uten atFetchParamskreves:
function useFetch<Data, FetchParams extends any[] = any[]>(
Men å gi en standardverdi hindrer at noen typklassifisering skjer, noe som gjør FetchParams ubrukelig, og vi er tilbake til å tvinge utvikleren til å sende inn argumentene hver gang, bare uten feilmelding/typpesikkerhet hvis de velger å ikke gjøre det.
Lenke til TypeScript-lekeplass