reactjs - Typescript cum să combini tipizarea dinamică ([key: type]: type) și tipizarea statică pentru o interfață


Problema principală

Nu sunt chiar sigur dacă acest lucru este posibil, dar fiindcă urăsc Typescript și îmi face codarea dificilă, m-am gândit să întreb doar ca să fiu sigur.

interface ISomeInterface {
  handler: () => {}
  [key: string]: string
}

Problema, evident, este că handler este un () => {} și nu un șir de caractere, așa că TypeScript aruncă o eroare. Este posibil cumva să facem să funcționeze asta?

Aditament :

Tot pe această temă, această interfață este destinată să fie utilizată de un React.Context și, deoarece React.createContext(/* necesită valoare implicită aici */) impune o valoare implicită, trebuie să îi ofer un obiect care să corespundă acelei interfețe. Când încerc să trec un literal de obiect astfel:

React.createContext({handler: () => {throw new Error('using default context')}})

Typescript face o zarvă spunând {handler:() => never} nu poate fi atribuit lui {handler:() => {}}. Există vreo modalitate de a face această interfață plauzibilă? Am încercat să fac ca interfața să implementeze () => any, dar tot nu a funcționat, vrea never explicit.

Editare #1:

Așa că am făcut câteva modificări, și anume:

interface IFormContext {
  $handleChange: (key?, val?) => void
  $registerField: (key?) => void
  [key: string]: { value: string } | ((key?, val?) => void)
}

Dar acum, când încerc să accesez câmpul astfel: const {[key]: { value }}=props, care este practic destructurarea cu o cheie dinamică, primesc următoarea eroare:

Property 'value' does not exist on type '{ value: string; } | ((key?: any, val?: any) => void)'.ts(2339)

Răspuns #1

Din păcate, proprietățile tale denumite trebuie să corespundă semnăturii indexului. În acest caz, deoarece cel puțin o proprietate este o funcție, poți folosi:

[cheie: string]: string | Funcție;

sau

[key: string]: any;

Ambele ar trebui să funcționeze.

Pentru adăugarea ta, () => {} înseamnă o funcție fără argumente care returnează un obiect gol, în timp ce funcția () => {throw new Error('using default context')} nu returnează nimic, de aceea apare eroarea. Există puțină confuzie legată de acoladele folosite în tipuri și în implementarea efectivă a funcției.

O funcție cu tipul () => {} este de fapt ceva de genul () => {return {}} sau () => ({}).

Pentru o funcție care nu returnează nimic, poți folosi never sau void, dar dacă handler-ul tău poate returna ceva, poți folosi ceva de genul handler:() => void | boolean, înlocuind boolean cu tipul pe care poate să-l returneze.