Cet article a fait l'objet d'une traduction automatique.
TypeScript
Comprendre TypeScript
À bien des égards, il est utile de penser à caractères dactylographiés sur ses propres mérites. La spécification du langage texte dactylographié se réfère à TypeScipt comme « un sucre syntaxique pour JavaScript ». C'est vrai et sans doute une étape essentielle pour parvenir à l'auditoire cible de la langue — développeurs côté client actuellement en utilisant JavaScript.
Et il ne faut pas comprendre JavaScript avant que vous puissiez comprendre le texte dactylographié. En fait, la spécification du langage (vous pouvez le lire à bit.ly/1xH1m5B) décrit souvent des constructions de texte dactylographié en ce qui concerne le code JavaScript résultant. Mais il est également utile d'envisager de tapuscrit comme un langage en soi qui partage des caractéristiques avec JavaScript.
Par exemple, comme C#, texte dactylographié est un langage de données typées, qui permet une prise en charge IntelliSense et compilation vérifier, entre autres fonctionnalités. Comme c#, tapuscrit comprend des expressions génériques et lambda (ou leur équivalent).
Mais tapuscrit, bien sûr, n'est pas c#. Comprendre ce qui est unique manuscrit dactylographié est aussi important que de comprendre ce que le texte dactylographié partage avec langage côté serveur que vous utilisez actuellement. Le système de type texte dactylographié est différent (et plus simple) que c#. Tapuscrit s'appuie sur sa compréhension des autres modèles d'objet de façon unique et exécute héritage contrairement à c#. Et parce que le texte dactylographié compile JavaScript, tapuscrit partage bon nombre de ses principes fondamentaux avec JavaScript, contrairement à c#.
Le reste, alors la question « vous écririez plutôt votre client -code de côté dans cette langue ou en JavaScript? "
Texte dactylographié est données typées
Tapuscrit n'a de nombreux types de données intégrés, vous pouvez utiliser pour déclarer des variables — juste string, number et Boolean. Ces trois types sont un sous-type de n'importe quel type (que vous pouvez également utiliser lorsque vous déclarez des variables). Vous pouvez définir ou vérifier les variables déclarées avec ces quatre types contre les types null ou undefined. Vous pouvez également déclarer des méthodes comme nulle, indiquant qu'ils ne retournent une valeur.
Cet exemple déclare une variable de chaîne :
var name: string;
Vous pouvez étendre ce système de type simple avec des valeurs énumérées et quatre sortes de types d'objets : interfaces, classes, fonctions et tableaux. Par exemple, le code suivant définit une interface (un genre de type d'objet) avec le nom ICustomerShort. L'interface comprend deux membres : une propriété appelée Id et une méthode appelée CalculateDiscount :
interface ICustomerShort
{
Id: number;
CalculateDiscount(): number;
}
Comme dans c#, vous pouvez utiliser les interfaces lorsque vous déclarez des variables et retournent des types. Cet exemple déclare les variables cs comme type de ICustomerShort :
var cs: ICustomerShort;
Vous pouvez également définir des types d'objets comme des classes, qui, contrairement aux interfaces, peuvent contenir du code exécutable. Cet exemple définit une classe nommée CustomerShort avec une propriété et une méthode :
class CustomerShort
{
FullName: string;
UpdateStatus( status: string ): string
{
...manipulate status...
return status;
}
}
Comme les versions plus récentes de c#, il n'est pas nécessaire de fournir le code d'implémentation lorsque vous définissez une propriété. La simple déclaration du nom et du type est suffisante. Les classes peuvent implémenter une ou plusieurs interfaces, comme le montre Figure 1, qui ajoute mon interface de ICustomerShort, avec sa propriété, à mon cours de CustomerShort.
Figure 1 Ajout d'une Interface à une classe
class CustomerShort implements ICustomerShort
{
Id: number;
FullName: string;
UpdateStatus(status: string): string
{
...manipulate status...
return status;
}
CalculateDiscount(): number
{
var discAmount: number;
...calculate discAmount...
return discAmount;
}
}
Comme Figure 1 montre, la syntaxe pour implémenter une interface est aussi simple en caractères dactylographiés comme dans c#. Pour implémenter les membres de l'interface, vous ajoutez simplement des membres portant le même nom au lieu de lier le nom de l'interface aux membres de la classe en question. Dans cet exemple, j'ai ajouté simplement Id et CalculateDiscount à la classe pour implémenter ICustomerShort. Texte dactylographié vous permet également d'utiliser des littéraux de type objet. Copiez le code suivant affecte la variable cst un objet littéral contenant une propriété et une méthode :
var csl = {
Age: 61,
HaveBirthday(): number
{
return this.Age++;
}
};
Cet exemple utilise un type d'objet pour spécifier la valeur de retour de la méthode UpdateStatus :
UpdateStatus( status: string ): {
status: string; valid: boolean }
{
return {status: "New",
valid: true
};
}
En plus des types d'objets (classe, interface, littéral et tableau), vous pouvez également définir des types de fonctions qui décrivent signature d'une fonction. Le code suivant réécrit CalculateDiscount de ma classe CustomerShort d'accepter un seul paramètre appelé discountAmount :
interface ICustomerShort
{
Id: number;
CalculateDiscount( discountAmount:
( discountClass: string,
multipleDiscount: boolean ) => number): number
}
Ce paramètre est défini à l'aide d'un type de fonction qui accepte deux paramètres (celui de la chaîne, celle de boolean) et renvoie un nombre. Si vous êtes un développeur c#, vous pourriez trouver que la syntaxe ressemble beaucoup à une expression lambda.
Une classe qui implémente cette interface ressemblerait Figure 2.
Figure 2, cette classe implémente l'Interface appropriée
class CustomerShort implements ICustomerShort
{
Id: number;
FullName: string;
CalculateDiscount( discountedAmount:
( discountClass: string,
multipleDiscounts: boolean ) => number ): number
{
var discAmount: number;
...calculate discAmount...
return discAmount;
}
}
Comme les versions récentes de c#, tapuscrit déduit également le type de données d'une variable de la valeur à laquelle la variable est initialisée. Dans cet exemple, le texte dactylographié assumera que la variable myCust est de CustomerShort :
var myCust= new CustomerShort();
myCust.FullName = "Peter Vogel";
Comme c#, vous pouvez déclarer des variables à l'aide d'une interface et puis définissez la variable à un objet qui implémente cette interface :
var cs: ICustomerShort;
cs = new CustomerShort();
cs.Id = 11;
cs.FullName = "Peter Vogel";
Enfin, vous pouvez également utiliser des paramètres de type (qui ressemblent étrangement à des génériques en c#) pour laisser le code appelant de spécifier le type de données à utiliser. Cet exemple permet le code qui crée l'ensemble de la classe, le type de données de la propriété Id :
class CustomerTyped<T>
{
Id: T;
}
Copiez le code suivant définit le type de données de la propriété Id à une chaîne avant de l'utiliser :
var cst: CustomerTyped<string>;
cst = new CustomerTyped<string>();
cst.Id = "A123";
Pour isoler les classes, les interfaces et les autres membres du public et éviter des collisions de noms, vous pouvez déclarer ces constructions à l'intérieur des modules tout comme les espaces de noms c#. Vous devrez marquer les éléments que vous souhaitez rendre accessibles aux autres modules avec le mot-clé exportation. Le module Figure 3 exporte deux interfaces et une classe.
Figure 3 exportation deux Interfaces et classes
module TypeScriptSample
{
export interface ICustomerDTO
{
Id: number;
}
export interface ICustomerShort extends ICustomerDTO
{
FullName: string;
}
export class CustomerShort implements ICustomerShort
{
Id: number;
FullName: string;
}
Pour utiliser les composants exportés, vous pouvez préfixer le nom du composant avec le nom du module comme dans cet exemple :
var cs: TypeScriptSample.CustomerShort;
Ou vous pouvez utiliser le mot-clé d'importation de texte dactylographié pour créer un raccourci vers le module :
import tss = TypeScriptSample;
...
var cs:tss.CustomerShort;
Texte dactylographié est souple sur le typage de données
Tout cela devrait paraître familier si vous êtes un programmeur c#, sauf peut-être le revirement des déclarations de variable (variable nom tout d'abord, type de données deuxième) et des littéraux en objet. Toutefois, pratiquement toutes les données tapant en caractères dactylographiés est facultative. La spécification décrit les types de données comme « annotations ». Si vous omettez des types de données (et le texte dactylographié ne déduire le type de données), types de données par défaut pour tout le type.
Texte dactylographié ne nécessite pas strict datatype correspondant, soit. Texte dactylographié utilise ce que la spécification appelle « sous-typage structurel » pour déterminer la compatibilité. Ceci est similaire à ce qu'on appelle souvent « duck-typing ». En caractères dactylographiés, deux classes sont considérés comme identiques s'ils ont des membres avec les mêmes types. Par exemple, voici un clientcourt classe implémentant une interface appelée ICustomerShort :
interface ICustomerShort
{
Id: number;
FullName: string;
}
class CustomerShort implements ICustomerShort
{
Id: number;
FullName: string;
}
Voici une classe appelée CustomerDeviant qui ressemble à ma classe CustomerShort :
class CustomerDeviant
{
Id: number;
FullName: string;
}
Grâce à une sous-typage structurel, je peux utiliser CustomerDevient avec des variables définies avec mon CustomerShort classe ou l'interface ICustomerShort. Ces exemples utilisent indifféremment CustomerDeviant avec les variables déclarées comme CustomerShort ou ICustomerShort :
var cs: CustomerShort;
cs = new CustomerDeviant
cs.Id = 11;
var csi: ICustomerShort;
csi = new CustomerDeviant
csi.FullName = "Peter Vogel";
Cette flexibilité vous permettent d'assigner littéraux d'objet texte dactylographié de variables déclarées comme des classes ou des interfaces, autant ils sont structurellement compatibles, car ils sont ici :
var cs: CustomerShort;
cs = {Id: 2,
FullName: "Peter Vogel"
}
var csi: ICustomerShort;
csi = {Id: 2,
FullName: "Peter Vogel"
}
Cela mène à des fonctionnalités spécifiques à tapuscrit autour des types apparents, super-types et sous-types conduisant à la question générale de cessibilité, que je vais sauter ici. Ces caractéristiques permettrait aux CustomerDeviant, par exemple, d'avoir des membres qui ne sont pas présents dans CustomerShort sans causer de mon exemple de code à l'échec.
Texte dactylographié a classe
La spécification de tapuscrit désigne la langue comme la mise en œuvre de « les classe modèle [aide] prototype chaînes à mettre en œuvre de nombreuses variations sur les mécanismes d'héritage orienté objet ». Dans la pratique, cela signifie que tapuscrit n'est pas seulement données typées, mais efficacement orienté objet.
De la même manière qu'une interface c# peut hériter d'une interface de base, une interface texte dactylographié peut s'étendre à une autre interface — même si cette autre interface est définie dans un module différent. Cet exemple étend l'interface de ICustomerShort pour créer une nouvelle interface appelée ICustomerLong :
interface ICustomerShort
{
Id: number;
}
interface ICustomerLong extends ICustomerShort
{
FullName: string;
}
L'interface de ICustomerLong aura deux membres : FullName et Id. Dans l'interface fusionnée, les membres de l'interface apparaissent d'abord. Par conséquent, mon interface ICustomerLong est équivalent à cette interface :
interface ICustomerLongPseudo
{
FullName: string;
Id: number;
}
Une classe qui implémente ICustomerLong aurait besoin de deux propriétés :
class CustomerLong implements ICustomerLong
{
Id: number;
FullName: string;
}
Classes peuvent s'étendre d'autres classes de la même manière qu'une interface peut s'étendre à un autre. La classe de Figure 4 étend CustomerShort et ajoute une nouvelle propriété à la définition. Il utilise explicites getters et setters pour définir les propriétés (mais pas d'une manière particulièrement utile).
Figure 4 propriétés définies avec les Getters et Setters
class CustomerShort
{
Id: number;
}
class CustomerLong extends CustomerLong
{
private id: number;
private fullName: string;
get Id(): number
{
return this.id
}
set Id( value: number )
{
this.id = value;
}
get FullName(): string
{
return this.fullName;
}
set FullName( value: string )
{
this.fullName = value;
}
}
Texte dactylographié applique les meilleures pratiques d'accéder à des champs internes (comme les id et fullName) faisant référence à la classe (cela). Les classes peuvent également avoir des fonctions de constructeurs qui proposent une fonction QUE C# vient d'adopter : Définition automatique des champs. La fonction de constructeur dans une classe de caractères dactylographiés doit être nommée constructeur et ses paramètres publics sont automatiquement définies comme propriétés et initialisés à partir des valeurs passées à eux. Dans cet exemple, le constructeur accepte un seul paramètre appelé société de type string :
export class CustomerShort implements ICustomerShort
{
constructor(public Company: string)
{ }
Parce que le paramètre de compagnie est défini comme public, la classe obtient également une propriété publique nommée entreprise initialisé à partir de la valeur passée au constructeur. Grâce à cette fonction, la variable maquette aura la valeur "PH & VIS," comme dans cet exemple :
var css: CustomerShort;
css = new CustomerShort( "PH&VIS" );
var comp = css.Company;
Déclarer un paramètre du constructeur comme privé crée une propriété interne, il ne peut être accessible à partir de code à l'intérieur des membres de la classe via le mot-clé cela. Si le paramètre n'est pas déclaré comme public ou privé, aucun bien n'est généré.
Votre classe doit avoir un constructeur. Comme dans c#, si vous ne fournissez pas un, on se fourni pour vous. Si votre classe étend une autre classe, un constructeur que vous créez doit inclure un appel à super. Cela appelle le constructeur de la classe, que c'est l'extension. Cet exemple inclut un constructeur avec un super appel qui fournit des paramètres au constructeur de la classe de base :
class MyBaseClass
{
constructor(public x: number, public y: number ) { }
}
class MyDerivedClass extends MyBaseClass
{
constructor()
{
super(2,1);
}
}
Texte dactylographié hérite différemment
Encore une fois, ce sera tout semblera familier si vous êtes un programmeur c#, à l'exception de quelques mots drôles (va). Mais, encore une fois, s'étendant à une classe ou une interface n'est pas tout à fait la même chose que les mécanismes d'héritage en c#. La spécification de texte dactylographié utilise les termes habituels de la classe s'étend ("la classe de base") et la classe qui étend ("classe dérivée »). Toutefois, la spécification désigne une classe « patrimoine cahier des charges, » par exemple, au lieu d'utiliser le mot « héritage ».
Dans un premier temps, texte dactylographié a moins d'options que c# quand il s'agit de définir les classes de base. Vous ne pouvez pas déclarer la classe ou les membres comme non substituable, abstraite ou virtuelle (bien que les interfaces fournissent la majeure partie de la fonctionnalité qui fournit une classe de base virtuelle).
Il n'y a aucun moyen de prévenir certains membres ne soient ne pas hérités. Une classe dérivée hérite de tous les membres de la classe de base, y compris le public et émanant des députés (tous les membres publics de la classe de base sont overrideable tandis que les membres privés ne sont pas). Pour remplacer un membre du public, il suffit de définir un membre dans la classe dérivée avec la même signature. Tandis que vous pouvez utiliser le mot clé super pour accéder à une méthode publique d'une classe dérivée, vous ne pouvez pas accéder à une propriété dans la classe de base à l'aide super (bien que vous pouvez substituer la propriété).
Texte dactylographié vous permet d'augmenter une interface en déclarant simplement une interface avec un nom identique et de nouveaux membres. Cela vous permet d'étendre le code JavaScript existant sans créer un nouveau type nommé. L'exemple de la Figure 5 définit l'interface de ICustomerMerge par le biais de deux définitions d'interface distincte et ensuite comment implémenter l'interface dans une classe.
La figure 5 l'Interface ICustomerMerge définie par l'intermédiaire de deux définitions d'Interface
interface ICustomerMerge
{
MiddleName: string;
}
interface ICustomerMerge
{
Id: number;
}
class CustomerMerge implements ICustomerMerge
{
Id: number;
MiddleName: string;
}
Classes peuvent également s'étendre d'autres classes, mais pas d'interfaces. En caractères dactylographiés, interfaces peuvent également étendre les classes, mais d'une manière qui met en cause héritage. Lorsqu'une interface étend une classe, l'interface comprend tous les membres de la classe (publics et privés), mais sans les implémentations de la classe. Dans Figure 6, l'interface de ICustomer aura l'id de membre privé, membre du public Id et le membre public MiddleName.
Figure 6 une classe étendue avec tous les membres
class Customer
{
private id: number;
get Id(): number
{
return this.id
}
set Id( value: number )
{
this.id = value;
}
}
interface ICustomer extends Customer
{
MiddleName: string;
}
L'interface de ICustomer possède une importante restriction — vous ne pouvez l'utiliser avec les classes qui étendent la classe même l'interface étendue (dans ce cas, c'est la classe Customer). Texte dactylographié nécessite que vous incluez des membres privés dans l'interface pour être héritée de la classe qui étend de l'interface, au lieu d'être de nouveau implémenté dans la classe dérivée. Une nouvelle classe qui utilise l'interface de ICustomer aurait besoin, par exemple, de fournir une implémentation pour le MiddleName (car elle est uniquement spécifiée dans l'interface). Les développeurs utilisant ICustomer pourraient choisir d'hériter ou substituer les méthodes publiques de la classe Customer, mais ne serait pas en mesure de substituer le membre id privé.
Cet exemple montre une classe (appelée NewCustomer) qui implémente l'interface ICustomer et étend la classe de client tel que requis. Dans cet exemple, NewCustomer hérite de la mise en œuvre de l'Id de client et fournit une implémentation pour le MiddleName :
class NewCustomer extends Customer implements ICustomer
{
MiddleName: string;
}
Cette combinaison d'interfaces, classes, mise en œuvre et extension fournit une façon contrôlée pour classes vous définissez afin d'étendre les classes définies dans d'autres modèles d'objet (pour plus de détails, consultez la section 7.3 de la spécification du langage, « Interfaces étendant Classes »). Associée à la capacité du texte dactylographié d'utiliser les informations concernant les autres bibliothèques JavaScript, il vous permet d'écrire le code texte dactylographié qui travaille avec les objets définis dans ces bibliothèques.
Texte dactylographié connaît vos bibliothèques
En plus de connaître les classes et interfaces définies dans votre application, vous pouvez fournir le tapuscrit avec informations sur les autres bibliothèques d'objets. Qui est gérée par le texte dactylographié déclarer mot-clé. Cela crée ce que les appels de la spécification « déclarations ambiantes. » Beaucoup jamais il faut utiliser le mot clé declare vous-même parce que vous pouvez trouver les fichiers de définition pour la plupart des bibliothèques JavaScript sur le site de DefinitelyTyped à definitelytyped.org. Par le biais de ces fichiers de définition, tapuscrit peut effectivement « lire la documentation » sur les bibliothèques avec lesquelles vous devez travailler.
« Lecture de la documentation, » bien sûr, signifie que vous obtenez des données -tapé en charge IntelliSense et compilation vérifier lorsque vous utilisez les objets qui composent la bibliothèque. Il permet également le tapuscrit, dans certaines circonstances, de déduire le type d'une variable à partir du contexte dans lequel il est utilisé. Grâce au fichier de définition de lib.d.ts accompagne ce texte dactylographié, tapuscrit suppose que l'ancrage de la variable est de type HTMLAnchorElement dans le code suivant :
var anchor = document.createElement( "a" );
Le fichier de définition précise qui est le résultat retourné par la méthode createElement, lorsque la chaîne est passé à la méthode « a ». Sachant l'ancre est un HTMLAnchorElement signifie tapuscrit sait la variable ancre soutiendra, par exemple, l'addEventméthode d'écouteur.
Les données de texte dactylographié l'inférence de type aussi fonctionne avec les types de paramètres. Par exemple, la méthode addEventListener accepte deux paramètres. Le second est une fonction en passant un objet de type PointerEvent addEventListener. Texte dactylographié qui sait et prend en charge l'accès à la propriété cancelBubble de la classe PointerEvent au sein de la fonction :
span.addEventListener("pointerenter", function ( e )
{
e.cancelBubble = true;
}
De la même manière que lib.d.ts fournit des informations sur le modèle DOM HTML, les fichiers de définition pour autre JavaScript fournissent des fonctionnalités similaires. Après avoir ajouté le fichier backbone.d.ts dans mon projet, par exemple, je peux déclarer une classe qui étend la classe de modèle de colonne vertébrale et ma propre interface avec le code comme ceci :
class CustomerShort extends bb.Model implements ICustomerShort
{
}
Si vous êtes intéressé par les détails sur comment utiliser texte dactylographié avec épine dorsale et Knockout, découvrez mes colonnes de texte dactylographié pratique à bit.ly/1BRh8NJ. Dans la nouvelle année, je rechercherai les détails d'utilisation de texte dactylographié avec angulaire.
Il n'y a plus de texte dactylographié que vous voyez ici. La version 1.3 de tapuscrit est prévue d'inclure les tuples et les types de données union (pour soutenir, par exemple, les fonctions qui retournent une liste de types particuliers). L'équipe de tapuscrit travaille avec d'autres équipes en appliquant les données tapant à JavaScript (débit et angulaire) pour assurer le que tapuscrit travaillera avec le plus large une gamme de JavaScript bibliothèques que possible.
Si vous avez besoin de faire quelque chose qui prend en charge le JavaScript et texte dactylographié ne vous laissera pas faire, vous pouvez toujours intégrer votre code JavaScript tapuscrit étant un sur-ensemble de JavaScript. Ainsi la question demeure : laquelle de ces langues vous préférez utiliser pour écrire votre code côté client ?
Peter Vogel est directeur chez PH & V Information Services, spécialisée dans le développement Web avec expertise en SOA, développement côté client et la conception de l'interface. PH & clients V incluent la Banque canadienne impériale de Commerce, de Volvo et de Microsoft. Il enseigne et écrit des cours pour Learning Tree International et écrit la colonne .NET pratique pour VisualStudioMagazine.com.
Merci à l'expert technique Microsoft suivant d'avoir relu cet article : Ryan Cavanaugh