Tworzenie obiektu na podstawie typów typescript

0

Pytanie

Żeby nie powiedzieć, że mam taki typ

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

Jak mogę dynamicznie utworzyć funkcję, która zwróci

{ go: '', start: '' }

Czy jest jakiś sposób, aby w skrypcie rodzaju dynamicznie generować pusty obiekt na podstawie typu? Lub jest to niemożliwe, ponieważ nie możemy po prostu się powiesił

Myślałem o czymś takim

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

Najlepsza odpowiedź

2

Po uruchomieniu kompilatora TypeScript (tsc) w celu przeniesienia kodu maszynopisu tekstu wykonywany JavaScript ściera system statycznych typów języka. Tak, że twój Foo typ (przemianowany w górnym rejestrze, zgodnie z konwencjami nazewnictwa TS) nie jest obecny ani w jakiej formie w czasie wykonywania. Nie ma nic, co można by powtórzyć, aby uzyskać klucze go i start.


Najprostszym sposobem, aby to osiągnąć coś się stało w czasie wykonywania, to napisz JavaScript, niezbędny do tego, a następnie upewnić się, że kompilator TypeScript może dostarczyć silnych typy, które są potrzebne, aż do jego pisania. Jest to w zasadzie odwrotna strona tego, co próbujesz zrobić.

W twoim przypadku: co sprawia, że generate() potrzebne do tego, aby pracować w czasie wykonywania? Dobrze, jeśli możemy założyć, że wartości generowanych przez generate() będą to obiekty zawierające tylko string-wartość właściwości, to musimy przekazać mu listę kluczy do obiektu. No i co z tego, jeśli napiszemy generate() aby to zrobić, a następnie określ Foo z punktu widzenia produkcji generate() a nie odwrotnie?

Na przykład:

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

Tutaj generate() jest uniwersalną funkcją, która przyjmuje lista kluczy (typu K) i zwraca wartość typu z kluczami w K i wartości typu string. Co {[P in K]: string} czy jest skojarzony typ odpowiadającym Record<K, string> za pomocą Record<K, V> typ użyteczności.

Realizacja używaObject.fromEntries() w celu utworzenia obiektu i typ zwracanej wartości jest zatwierdzony jako odpowiedni typ, bo TypeScript widzi Object.fromEntries() jak zwraca typ, który jest zbyt szeroki dla naszych celów.

W każdym przypadku, gdy zadzwonisz const myFooObject = generate("go", "start")tworzy wartość typu {go: string; start: string}, że zgadza się z twoim Foo Typ. Więc możemy po prostu ustalić Foo jak type Foo = typeof myFooObject zamiast robić to ręcznie. Czy wszystko można jeszcze zrobić to ręcznie, ale istotą, którą ja tutaj pokazuję, polega na tym, że o wiele łatwiej pisać SUCHEJ kod w TypeScript, jeśli zaczniesz z wartości i tworzyć typy z nich, zamiast próbować zrobić to odwrotnie.


Ponownie, jeśli korzystasz z kompilator TypeScript tsc jak jest, następnie kasowanie typu nie pozwala ci pisać generate() z definicji pojęcia Foo. Ale...

Jeśli chcesz dodać etap montażu w swój projekt i wykonanie generowanie kodu za pomocą API kompilatora TypeScript lub coś w tym rodzaju, można wykonywać dowolne czynności z typami. Istnieją biblioteki, które robią to samo co ty; na przykład, ts-auto-mock twierdzi, że tworzy fikcyjne obiekty z danego typu obiektu, który dokładnie pasuje do twojego wariantu użytkowania.

Taki dodatkowy krok złożenia może być rozsądne podejście dla ciebie, ale jeśli pójdziesz tą drogą, należy zauważyć, że nie używasz już zwykły maszynopisu tekst (i, w konsekwencji, temat, prawdopodobnie wykracza poza wydania tylko z tagiem maszynopisu tekstu).

Link do zabaw dla kodu

2021-11-25 04:07:53
1

Można zrobić go uniwersalnym, oto tak:

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

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

Plac zabaw dla pisania

2021-11-23 19:47:19

W innych językach

Ta strona jest w innych językach

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