Vytvořit objekt na základě typů typescript

0

Otázka

Jinak říct, že mám tento typ

type foo = {
 go: string;
 start: string;
}

Jak mohu dynamicaly udělal funkci, která vrátí

{ go: '', start: '' }

Existuje nějaký způsob, jak na Typ Skriptu můžeme dynamicky vytvořit prázdný objekt, na základě pouze jen typ? Nebo to je nemožné, protože nemůžeme jen smyčka

Myslel jsem něco, jako jsou tyto

function generate<T>(T)<T>  {
 const obj = {}
 for (const key of keyof T) {
   obj[key] = ''
 }
 return obj
}
typescript
2021-11-23 19:36:25
2

Nejlepší odpověď

2

Při spuštění TypeScript compiler (tsc) transpile TypeScript kód do spustitelného JavaScript, jazyk je statický typový systém je vymazán. Takže vaše Foo typ (přejmenován na velká písmena, aby splňovaly TS konvence pojmenování) není přítomen v nějaké formě na runtime. Neexistuje nic, co můžete iterovat přes do dostat klíče go a start.


Nejpřímější způsob, jak dostat něco, co se stane při běhu, je napsat v Javascriptu nutné, aby to, a pak se ujistěte se, že TypeScript compiler může dát silný typy, které potřebujete, když jste to psal. To je v podstatě reverzní toho, co se snažíte udělat.

Ve vašem případě: to, co dělá generate() potřebujete k práci na běhu? No, pokud můžeme předpokládat, že hodnoty generované generate() budou objekty, které drží pouze string-oceňují vlastnosti, pak musíme projít seznam klíčů od objektu. Tak co kdyby jsme se napsat generate() k tomu, že, a pak definovat Foo z hlediska výstupu generate() místo toho naopak?

Například:

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": ""
} */

Zde generate() je generická funkce, která vezme seznam klíčů (typu K) a produkuje hodnotu typu s klávesami v K a hodnoty typu string. Že {[P in K]: string} je mapována typ ekvivalentní Record<K, string> použití na Record<K, V> utility typu.

Implementace používá Object.fromEntries() na stavbu objektu, a návratový typ je tvrdil být správný typ, protože vidí, Strojopis Object.fromEntries() jako vracející se na typ, který je příliš široký pro naše účely.

Každopádně, když budete volat const myFooObject = generate("go", "start")to produkuje hodnotu typu {go: string; start: string}, který je stejný jako váš Foo typ. Takže můžeme jen definovat Foo jako type Foo = typeof myFooObject místo toho dělal to ručně. Jsi mohl stále dělat to ručně, ale jde mi o to, že ukazujeme zde, že je mnohem jednodušší napsat SUCHÉ kód na Stroji, pokud začnete s hodnotami a vytvořit typů z nich, místo toho se snaží dělat to opačně.


Opět, pokud používáte TypeScript compiler tsc tak, jak je, potom zadejte výmaz vám brání psát generate() z definice Foo. Ale...

Pokud jste ochotni přidat budovat krok k projektu a provádět generování kódu pomocí TypeScript compiler API nebo něco takového, pak můžete dělat libovolné věci s typy. Existují knihovny, které dělat podobné věci, aby to, co chcete, například, ts-auto-mock nároky pro generování mock objekty typ objektu, který vypadá jako přesně váš případ použití.

Jako extra budovat krok by mohl být rozumný přístup pro vás, ale pokud budete jít dolů, že trasu, kterou by si měli uvědomit, že nejste používáte jen obyčejný Strojopis už (a proto téma je asi mimo rozsah pro otázku s několika Stroji tag).

Hřiště odkaz na kód

2021-11-25 04:07:53
1

Mohl byste to udělat obecný, jako je tento:

type foo<T extends string = string> = {
    go: T;
    start: T;
}

const test: foo<''> = {
    go: '',
    start: '',
};

Strojopis Hřiště

2021-11-23 19:47:19

V jiných jazycích

Tato stránka je v jiných jazycích

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................