Lorsque vous exécutez le fichier d'enregistrement du compilateur (tsc
) pour transpile Tapuscrit code exécutable JavaScript, le langage du système de type statique est effacé. Si votre Foo
type (renommé en majuscules pour répondre à TS les conventions de nommage) n'est pas présent dans le formulaire au moment de l'exécution. Il n'y a rien que vous pouvez parcourir à la remise des clés go
et start
.
La façon la plus simple d'obtenir quelque chose pour arriver à l'exécution est d'écrire le code JavaScript nécessaire pour le faire, puis assurez-vous que le Tapuscrit compilateur peut vous donner les fortes vous avez besoin pendant que vous l'écrivez. C'est essentiellement l' inverse de ce que vous essayez de faire.
Dans votre cas: ce n' generate()
besoin pour travailler au moment de l'exécution? Eh bien, si nous pouvons supposer que les valeurs générées par generate()
seront des objets ayant seulement string
valeur des propriétés, alors nous avons besoin de passer à une liste des clés de l'objet. Alors que faire si nous écrire generate()
pour le faire, et puis de définir Foo
en termes de la sortie de generate()
au lieu de l'inverse?
Par exemple:
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": ""
} */
Ici generate()
est un générique de fonction qui prend une liste de clés (de type K
) et produit une valeur d'un type avec des touches de K
et les valeurs de type string
. Que {[P in K]: string}
est mappé type équivalent à Record<K, string>
à l'aide de la Record<K, V>
de type utilitaire.
La mise en œuvre utilise Object.fromEntries()
pour construire l'objet, et le type de retour est affirmé être le type de droit parce que Tapuscrit voit Object.fromEntries()
comme retournant un type qui est trop large pour nos fins.
De toute façon, lorsque vous appelez const myFooObject = generate("go", "start")
il produit une valeur de type {go: string; start: string}
, qui est le même que celui de votre Foo
type. Nous pouvons donc définir Foo
comme type Foo = typeof myFooObject
au lieu de le faire manuellement. Vous pourrait toujours le faire manuellement, mais le point que je vais les montrer ici, c'est que c'est beaucoup plus facile d'écrire à SEC code en caractères d'imprimerie si vous commencez avec des valeurs et de générer des types d'eux, au lieu d'essayer de le faire dans l'autre sens.
Encore une fois, si vous utilisez le Tapuscrit compilateur tsc
que-est, puis le type d'effacement ne vous empêche de l'écriture generate()
à partir de la définition de Foo
. Mais...
Si vous êtes prêt à ajouter une étape de génération de votre projet et d'effectuer la génération de code à l'aide de la Tapuscrit compilateur API ou quelque chose comme cela, vous pourrez alors faire arbitraire des choses avec les types. Il y a des bibliothèques qui font des choses similaires à ce que vous voulez, par exemple, ts-auto-se moquer de revendications pour générer des objets fantaisie donné un type d'objet, qui ressemble exactement à votre cas d'utilisation.
Un tel supplément de construire étape pourrait être une approche raisonnable pour vous, mais si vous allez dans cette voie, vous devez noter que vous n'êtes pas en utilisant simplement le Tapuscrit plus (et donc le sujet est probablement hors de portée pour une question avec juste un Tapuscrit de la balise).
Aire de jeux lien vers le code