Utilisation d'un type comme paramètre Typescript

Sep 29 2020

comment utiliser un type comme paramètre dans Typescript

type myType = {}
const passingType = (t: Type) => {
    const x : t = {}
}

passingType(myType);

J'obtiens des erreurs TS

't' refers to a value, but is being used as a type here. Did you mean 'typeof t'?

et

'myType' only refers to a type, but is being used as a value here.ts(2693)

pour l'appel

toute idée sur la façon d'accomplir cela.

Réponses

2 jcalz Sep 29 2020 at 14:44

Ce n'est pas possible.


Le système de type statique de TypeScript (qui comprend votre myTypedéfinition et les annotations de type) est effacé lorsque le code est émis en JavaScript. JavaScript est ce qui s'exécute réellement au moment de l'exécution. Lors de l'exécution, vous ne pouvez accéder qu'aux valeurs . L'effacement de type signifie que votre code ci-dessus devient quelque chose comme ceci:

const passingType = (t) => {
    const x = {};
};
passingType(myType);

Il n'y a aucune valeur nommée myTypeà laquelle passer passingType.

Et comme les types TypeScript n'existent pas en tant que valeurs au moment de l'exécution, il n'y a pas de "type de types" comme ce que vous appelez Type. Donc, cette approche, comme indiqué, n'est pas directement possible.


Au lieu de penser à passer un "type" à une fonction lors de l'exécution, ce qui n'est pas fructueux, il est probablement préférable de réfléchir spécifiquement à ce que vous voulez qu'il se passe lors de l'exécution en JavaScript pur, puis d'écrire des types pour le supporter.

Que voudriez-vous vraiment faire avec un "type" au moment de l'exécution? Voulez-vous l'utiliser pour vérifier si une valeur est de ce type? Ensuite, au lieu de passer un type, vous voudrez peut-être passer une fonction de garde de type :

type Guard<T> = (x: any) => x is T;
const passingType = <T,>(t: Guard<T>) => {
    if (t(undefined)) {
        console.log("undefined IS of the guarded type T");
    }  else {
        console.log("undefined is NOT of the guarded type T");
    }
}

Et vous pouvez l'utiliser comme ceci:

function isUndefined(x: any): x is undefined {
    return typeof x === "undefined";
}

passingType(isUndefined); // undefined IS of the guarded type T

function isNumber(x: any): x is number {
    return typeof x === "number";
}
passingType(isNumber); // undefined IS NOT of the guarded type T

function isNumberOrUndefined(x: any): x is number | undefined {
    return isNumber(x) || isUndefined(x);
}

passingType(isNumberOrUndefined); // undefined IS of the guarded type T

Votre cas d'utilisation réel déterminera les exigences pour ce à quoi l'argument passingTypedoit ressembler. Il peut s'agir d'une structure de données complète représentant diverses choses que vous voudriez faire avec un "type" au moment de l'exécution. Donc, même si cet exemple de type guard ne fonctionne pas pour vous, il est possible que quelque chose d'autre le fasse.


Mais encore une fois, la réponse courte est que le système de type statique de TypeScript est effacé et qu'il est donc impossible de faire référence à ses types directement à l'exécution.

Lien Playground vers le code

1 CertainPerformance Sep 29 2020 at 14:43

Utilisez plutôt des génériques. Les arguments de type ont une syntaxe différente des arguments JS émis. Par exemple:

type TheType = |
  { foo: string } |
  { bar: string };
const passingType = <T extends TheType>(obj: T) => {
    return { ...obj };
};

const result = passingType({ foo: 'foo' });

Il en résulte resultqu'un nouvel objet créé à l'intérieur de la fonction est saisi correctement comme { foo: string }.