Când executați Script compiler (tsc
) pentru a transpile mașina de Scris cod în runnable JavaScript, un limbaj static tip de sistem este șters. Deci Foo
tip (redenumit în majuscule pentru a satisface TS convențiile de denumire) nu este prezent în orice formă în timpul rulării. Nu este nimic nu se poate repeta peste pentru a obține cheile go
și start
.
Cel mai simplu mod de a obține ceva să se întâmple la runtime este de a scrie JavaScript necesar să o facă, și apoi să asigurați-vă că mașina de Scris compiler poate da puternic tipuri aveți nevoie în timp ce scrii. Aceasta este de fapt inversa a ceea ce încerci să faci.
În cazul tău: ce înseamnă generate()
nevoie pentru a lucra la runtime? Ei bine, dacă putem presupune că valorile generate de generate()
vor fi obiecte care deține doar string
-proprietăți evaluate, atunci trebuie să-l treacă o listă de cheile de la obiect. Deci, ce dacă am scrie generate()
pentru a face asta, și apoi să definească Foo
în ceea ce privește producția de generate()
în loc de invers?
De exemplu:
function generate<K extends PropertyKey>(...keys: K[]) {
return Object.fromEntries(keys.map(k => [k, ""])) as { [P in K]: string };
}
const myFooObject = generate("go", "start");
type Foo = typeof myFooObject;
/* type Foo = {
go: string;
start: string;
} */
console.log(myFooObject)
/* {
"go": "",
"start": ""
} */
Aici generate()
este un generic funcție care ia o listă de chei (de tip K
) și produce o valoare de un tip cu cheile în K
și valori de tip string
. Asta {[P in K]: string}
este un mapate tip echivalent cu Record<K, string>
folosind cele Record<K, V>
tip de utilitate.
Implementarea folosește Object.fromEntries()
pentru a construi un obiect, și de tipul de retur este afirmat a fi tipul potrivit pentru mașina de Scris vede Object.fromEntries()
ca întorcându-se de un tip care e prea mare pentru scopurile noastre.
Oricum, atunci când apelați const myFooObject = generate("go", "start")
, se produce o valoare de tip {go: string; start: string}
, care este la fel ca dvs. Foo
tip. Deci, putem defini Foo
ca type Foo = typeof myFooObject
în loc de a face asta manual. Ai putea încă să-l facă manual, dar vreau să-ți arăt aici este că e mult mai ușor să scrie USCAT codul în mașina de Scris dacă începi cu valorile și de a genera tipuri de la ei, în loc de a încerca să-l facă invers.
Din nou, dacă sunteți folosind mașina de Scris compiler tsc
ca atare, apoi tastați ștergerea vă împiedică de la scris generate()
din definiția de Foo
. Dar...
Dacă sunteți dispus să adăugați o construi pas pentru proiectul dumneavoastră și de a efectua generarea de cod folosind mașina de Scris compiler API sau ceva de genul acesta, atunci puteți face lucruri arbitrare cu tipuri. Există biblioteci care fac lucruri similare cu ceea ce vrei; de exemplu, ts-auto-mock pretinde pentru a genera obiecte machete dat un tip de obiect, care se pare ca exact cazul dumneavoastră de utilizare.
Astfel un plus de a construi pas ar putea fi o abordare rezonabilă pentru tine, dar dacă te duci în jos ca traseu vă rugăm să rețineți că nu sunteți folosind pur și simplu mașina de Scris mai (și, prin urmare, subiectul este, probabil, în afara domeniului de aplicare pentru o întrebare cu doar un Script tag).
Loc de joaca link-ul de la cod