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 unarray
. 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)?
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.
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
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).
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.