TypeScript
est que la vérification de type est centrée sur la forme des valeurs.
Ceci est parfois appelé "typage de canard"
ou "sous-typage structurel"
.
Dans TypeScript
, les interfaces remplissent le rôle de nommer ces types et constituent un moyen puissant de définir des
contrats dans votre code ainsi que des contrats avec du code situé en dehors de votre projet.
printLabel
.
La fonction printLabel
a un paramètre unique qui nécessite que l'objet transmis possède une propriété appelée label
de type chaîne.
Notez que notre objet a en réalité plus de propriétés que cela, mais le compilateur vérifie seulement qu'au moins celles requises sont présentes et correspondent aux types requis.
Il existe des cas où TypeScript
n'est pas aussi clément, et nous en parlerons.LabelledValue
est un nom que nous pouvons maintenant utiliser pour décrire l'exigence de l'exemple précédent.
Cela représente toujours d'avoir une seule propriété appelée label
de type chaîne.
Notez que nous n'avions pas besoin de dire explicitement que l'objet que nous passons à printLabel
implémente cette interface comme nous pourrions le faire dans d'autres languages.
Ici, seule la forme compte. Si l'objet que nous transmettons à la fonction remplit les conditions énumérées, il est autorisé.?
à la fin du nom de la propriété dans la déclaration.color
dans createSquare
, nous aurions reçu un message d'erreur nous informant :readonly
avant le nom de la propriété :x
et y
ne peuvent plus être modifiés.TypeScript
est fourni avec un type ReadonlyArray‹T›
identique à Array‹T›
avec toutes les méthodes de mutation supprimées.
Vous pouvez ainsi vous assurer que vous ne modifiez pas vos tableaux après la création :ReadonlyArray
à un tableau normal est illégal.
Vous pouvez toujours le remplacer par une assertion de type, cependant :readonly
vs const
readonly
ou const
est de demander si vous l'utilisez sur une variable ou une propriété.
Les variables utilisent const
alors que les propriétés utilisent en lecture seule.TypeScript
nous permet de passer {size: number; label: string;}
à quelque chose qui n'attendait qu'un {label: string;}
.
Nous venons également d'apprendre les propriétés facultatives et leur utilité pour décrire ce que l'on appelle des "poches d'options".JavaScript
.
Par exemple, prenons notre dernier exemple en utilisant createSquare
:createSquare
est orthographié colour
plutôt que color
. En clair, ce genre de chose échoue en silence.width
sont compatibles,
qu'il n'ya pas de propriété color
, et que la propriété extra colour
est non significative.TypeScript
considère qu'il existe probablement un bogue dans ce code. Les littéraux d'objet reçoivent un traitement spécial
et sont soumis à une vérification de propriété excessive lors de leur affectation à d'autres variables ou de leur transmission en tant qu'arguments.
Si un littéral d'objet a des propriétés que le "type de cible" n'a pas, vous obtiendrez une erreur.SquareConfig
peut avoir des propriétés de color
et de width
avec
les types ci-dessus, mais peut également avoir un nombre quelconque d'autres propriétés, nous pourrions le définir comme suit :SquareConfig
peut avoir un nombre quelconque de propriétés,
et tant qu'elles ne sont pas de color
ou de width
, leur type importe peu.squareOptions
ne subira pas de vérifications de propriétés excessives, le compilateur ne vous indiquera pas d'erreur.color
ou une propriété de colour
à createSquare
,
vous devez corriger la définition de SquareConfig
afin de refléter cela.JavaScript
.
En plus de décrire un objet avec des propriétés, les interfaces sont également capables de décrire les types de fonction.TypeScript
peut en déduire les types d'argument
puisque la valeur de la fonction est directement affectée à une variable de type SearchFunc
.
Ici aussi, le type de retour de notre expression de fonction est impliqué par les valeurs renvoyées (ici false
et true
).
Si l'expression de la fonction avait renvoyé des nombres ou des chaînes, le vérificateur de type nous aurait averti
que le type de retour ne correspond pas au type de retour décrit dans l'interface SearchFunc
.a[10]
ou ageMap["daniel"]
.
Les types indexables ont une signature d'index qui décrit les types que nous pouvons utiliser pour indexer dans l'objet,
ainsi que les types de retour correspondants lors de l'indexation. Prenons un exemple :StringArray
qui a une signature d'index.
Cette signature d'index indique que lorsqu'un StringArray
est indexé avec un number
, il renvoie un string
.string
et number
.
Il est possible de prendre en charge les deux types d'indexeur, mais le type renvoyé par un indexeur numérique doit être
un sous-type du type renvoyé par l'indexeur de chaîne. En effet, lors de l'indexation avec un nombre, JavaScript
le convertira
en chaîne avant l'indexation en un objet. Cela signifie que l'indexation avec 100
(est un number
) est identique à l'indexation avec "100"
(est un string
),
de sorte que les deux doivent être cohérents.obj.property
est également disponible en tant que obj["property"]
.
Dans l'exemple suivant, le type name
ne correspond pas au type de l'index de chaîne et le vérificateur de type génère une erreur :myArray[2]
car la signature d'index est en lecture seule.C#
et Java
,
celui de forcer explicitement une classe à respecter un contrat particulier, est également possible dans TypeScript
.setTime
dans l'exemple ci-dessous:ClockConstructor
pour le constructeur et ClockInterface
pour les méthodes d'instance.
Ensuite, pour plus de commodité, nous définissons une fonction constructeur createClock
qui crée des instances du type qui lui est transmis.createClock
est de type ClockConstructor
, dans createClock(AnalogClock, 7, 32)
,
il vérifie que AnalogClock
dispose de la signature de constructeur correcte.JavaScript
.
En raison de la nature dynamique et flexible de JavaScript
, vous pouvez parfois rencontrer un objet qui fonctionne comme une combinaison de certains des types décrits ci-dessus.JavaScript
tiers, vous devrez peut-être utiliser des modèles tels que ceux décrits ci-dessus pour décrire complètement la forme du type.SelectableControl
contient tous les membres de Control
, y compris la propriété private state
.
étant donné que state
est un membre privé, seuls les descendants de Control
peuvent implémenter SelectableControl
.
En effet, seuls les descendants de Control
auront un membre privé d'état issu de la même déclaration, ce qui oblige les membres privés à être compatibles.Control
, il est possible d'accéder au membre privé d'état via une instance de SelectableControl
.
Effectivement, un SelectableControl
agit comme un contrôle connu pour avoir une méthode de sélection.
Les classes Button
et TextBox
sont des sous-types de SelectableControl
(car ils héritent tous deux de Control
et ont une méthode select
),
mais pas les classes Image
et Location
.