Quelle est la différence entre le Type(T) générique et n'importe quel type en caractères typographiques?

Quelle est la différence entre generic Type(T) et any en caractères d'imprimerie?

Fonction 1

function identity(arg: any): any {
    return arg;
}

Fonction 2

function identity<T>(arg: T): T {
    return arg;
}

Fonction 3

function identity<T>(arg: T[]): T[] {
    return arg;
}

la fonction 1 & 3 est acceptée si nous passons n'importe quelle sorte de data type, Mais la fonction 2 n'accepte pas si on passe un array. type générique est d'accepter tous les types de type de données sur le temps de compilation. mais ici, pourquoi ne pas accepter?

quelle fonction est bonne pour une meilleure performance ( fonction 1 ou Fonction 3)?

28
demandé sur Hyyan Abo Fakher 2017-05-17 14:04:38

4 réponses

il n'y a pas de différence si c'est une fonction d'identité qui retourne juste un argument et utilisé sans restrictions de type:

const foo: any = fn(['whatever']);

Et il y a une différence de tapé le code:

const foo: string = fn('ok');
const bar: string = fn([{ not: 'ok' }]);

en outre, l'utilisation du type générique fournit la sémantique. Cette signature suggère que la fonction n'est pas typée et renvoie n'importe quoi:

function fn(arg: any): any { ... }

cette signature suggère que la fonction renvoie le même type que son argument:

function fn<T>(arg: T): T { ... }

Réel les fonctions sont habituellement plus significatives que juste return arg exemple. Le type générique peut bénéficier de restrictions de type (tandis que any ne peuvent évidemment pas):

function fn<T>(arg: T[]): T[] {
  return arg.map((v, i) => arg[i - 1]);
}

mais les avantages deviennent plus évidents lorsque la fonction est utilisée en conjonction avec d'autres classes génériques et fonctions génériques (et éliminée si non génériques sont impliqués):

function fn<T>(arg: T[]): T[] {
  return Array.from(new Set<T>(arg));
}

Cela permet de maintenir constamment T type entre input (argument) et output (returned valeur):

const foo: string[] = fn(['ok']);
const bar: string[] = fn([{ not: 'ok' }]);

il ne peut y avoir de différence dans les performances car les types dactylographiés n'existent qu'au moment de la conception.

19
répondu estus 2017-05-22 12:11:33

il n'y a absolument aucune différence de performance en utilisant n'importe laquelle de ces méthodes, parce que toutes ces choses de fantaisie sont juste Typescript sucres, et est seulement pour le développement.

toute la vérification de type se fait uniquement en temps de compilation (lorsque le code est transposé/transformé en javascript normal, dans votre serveur ).

dans tous les cas, lorsque votre code est envoyé au navigateur de l'utilisateur, voici à quoi il ressemble:

function identity(arg){
    return arg;
}

Mais pour expliquer l' différences :

en utilisant any vous perdrez tous les contrôles de type et de sécurité que le script offre, alors que,T se comporte comme une variable qui retiendra le Type que vous ne connaissez pas.

function identity<T>(arg: T): T {
    return arg;
}

ci-dessus, nous savons que si identify accepte number , il sera de retour number et ainsi de suite, où que :


function identity(arg: any): any {
    return arg;
}

Mais maintenant, vous ne savez pas si arg et la returned valeur sont du même type ou non.


L'autre question T will solve est lorsque vous créez une méthode à l'intérieur d'une classe et qu'elle attend un argument que vous voulez vous assurer que cette méthode n'acceptera que les arguments avec le même type d'argument du constructeur de la classe lorsque instancié.

export class MyClass<T>{

   myMethod(anotherArg:T){}

}

Donc, en utilisant ci-dessus :

let str = "string";
let instance = new MyClass(str);
instance.myMethod("other string") // will compile

Où :

let num = 32423423;
let instance = new MyClass(num);
instance.myMethod("other string") // won't compile
13
répondu Milad 2017-05-17 11:45:44

l'usage principal de T pour éviter de casser le type lorsque vous appelez une méthode.

Exemple:

Si vous n' :

let foo = new Foo();
identity(foo).bar();

La deuxième ligne sera ok pour le compilateur, mais pas parce qu'il sait que bar existe Foo tapez, parce que c'est any et any peut avoir n'importe quelle méthode.

Si vous n' :

let foo = new Foo();
identity<Foo>(foo).bar();
identity<Foo>(foo).notExistingMethod();

la deuxième ligne compilera fine, pas la troisième parce que Foo n'a pas de notExistingMethod méthode.

tout est souvent utilisé lorsque vous avez besoin de créer quelque chose D'une manière plus Javascript, ce qui signifie que vous ne savez pas vraiment ce qu'il y a dans votre objet, puisque Javascript n'a aucun type (Je ne parle pas de es6 ofc).

2
répondu Supamiu 2017-05-17 11:13:53

Tout est any sur l'exécution et sur le dessus de qui c'est any au moment de la compilation JavaScript. C'est pourquoi il est TypeScript pour fournir le type de sécurité au moment de la compilation.

La différence entre any et T/T extends etc. est-ce que vous avez la sécurité de type pendant le temps de compilation par exemple

protected typeSafety = <T extends String>(args:T):T =>{
    return args;
}

this.typeSafety(1); // compile error
this.typeSafety("string"); // good to go

si la fonction accepte quoi que ce soit, vous aurez l'erreur à l'exécution, ce qui sera trop tard.

2
répondu Murat Karagöz 2017-05-17 11:17:55