reactjs - Typescript hur man blandar dynamisk ([key: typ]: typ) och statisk typning för ett gränssnitt
Huvudfråga
Inte riktigt säker på om detta är möjligt, men eftersom jag avskyr Typescript och det gör mitt kodande svårt, tänkte jag att jag skulle fråga bara för att vara säker.
interface ISomeInterface {
handler: () => {}
[key: string]: string
}
Problemet är uppenbarligen att handler är en () => {} och inte en sträng, så TypeScript ger ett fel. Är det möjligt att på något sätt få detta att fungera?
Tillägg:
Medan vi är inne på ämnet, ska detta gränssnitt användas av en React.Context och eftersom React.createContext(/* requires default here */) kräver ett standardvärde, behöver jag ge det ett objekt som matchar det gränssnittet. När jag försöker skicka ett objektliteral som detta:
React.createContext({handler: () => {throw new Error('using default context')}})
Typescript ställer till problem genom att säga {handler:() => never} kan inte tilldelas till {handler:() => {}}. Finns det något sätt att göra detta gränssnitt rimligt? Jag försökte få gränssnittet att implementera () => any, men det fungerade fortfarande inte, det vill ha explicit never.
Redigera #1:
Så jag har gjort några ändringar, nämligen:
interface IFormContext {
$handleChange: (key?, val?) => void
$registerField: (key?) => void
[key: string]: { value: string } | ((key?, val?) => void)
}
Men nu, när jag försöker komma åt fältet på det här sättet: const {[key]: { value }}=props som i princip är destrukturering med en dynamisk nyckel, får jag följande fel:
Property 'value' does not exist on type '{ value: string; } | ((key?: any, val?: any) => void)'.ts(2339)
Svar #1
Tyvärr måste dina namngivna egenskaper matcha indexsignaturen. I det här fallet, eftersom minst en egenskap är en funktion, kan du använda:
[key: string]: string | Funktion;
eller
[key: string]: any;Båda bör fungera.
Som en tillägg, () => {} betyder en funktion utan argument som returnerar ett tomt objekt, medan funktionen () => {throw new Error('using default context')} inte returnerar något, därav felet. Det finns lite förvirring med de klamrar som används i typer och i själva funktionsimplementeringen.
En funktion med typen () => {} är egentligen något som () => {return {}} eller () => ({}).
För en funktion som inte returnerar något kan du använda never eller void, men om din handler kan returnera något, kan du använda något som handler:() => void | boolean, där du ersätter boolean med den typ som den kan returnera.