2

J'étudie actuellement le typage structurel. Je suis sceptique quant à l'idée que deux types sont considérés comme équivalents simplement parce qu'ils ont une partie de leur structure en commun. Cela ressemble beaucoup à un typage de canard statique et il ignore complètement le niveau sémantique des types. Alors j'ai regardé de plus près la saisie structurelle de flux d'objets ordinaires et ont rencontré le comportement suivant:Est-ce que le sous-typage structurel du flux "oublie" des propriétés de sous-types spécifiques?

const o:{} = {foo: true}; 
o.foo; // type error 

{} est un type de structure et supertype de tous les objets ordinaires. Par conséquent, il est logique que je puisse annoter o avec lui, car {foo: true} est un sous-type structurel de {}. Toutefois, lorsque j'essaie d'accéder à la propriété foo existante, cette opération ne vérifie pas de type. Ceci est étrange car AFAIK un sous-type structurel peut généralement contenir des propriétés spécifiques tant qu'il inclut également toutes les propriétés requises de son supertype.

Il semble que l'algorithme de sous-typage structurel de flux oublie parfois des propriétés spécifiques à un certain sous-type. Est-ce que ce comportement est prévu ou est-ce que je viens juste de tomber dans un cas limite?

+1

Pourriez-vous préciser ce que vous voulez dire? En déclarant le type ': {}', vous avez explicitement effacé les informations de type à ce sujet, comme si vous aviez 'Animal foo = new Cat()', 'foo' ne sait pas que c'est un' Cat', sait juste que c'est un 'Animal'. – loganfsmyth

+0

@loganfsmyth '{}' est juste le type d'objet ordinaire le plus général sans aucune structure. C'est assez inutile bien sûr.La question est de savoir si le comportement que j'ai observé avec ce cas limite fait partie d'un problème plus profond, qui est spécifique au sous-typage. – ftor

+1

Ce que j'essaie de clarifier est, qu'en est-il de ce que vous voyez un cas d'un bord, et qu'en serait-il un problème? Dans le cas de JavaScript en tant que langage non typé, il y a absolument des cas où vous aurez un objet et ne connaîtrez rien sur les propriétés dont il dispose. Pour obtenir 'foo', vous pouvez faire' if (typeof o.foo === "booléen") {/ * faire des choses avec la propriété comme un booléen * /} 'et ça marchera très bien. – loganfsmyth

Répondre

3

Le problème global que vous décrivez est un fait de la conversion d'un sous-type en un super-type. En exécutant la conversion, vous demandez explicitement au compilateur de supprimer les informations sur un objet donné.

Par exemple, même sans taper la structure, si vous

class Animal {} 

class Cat extends Animal { 
    foo: bool = true; 
} 

const c: Animal = new Cat(); 

console.log(c.foo); 

(On flow.org/try)

il ne parvient pas à typer pour la même raison. Dans votre exemple vous avez explicitement dit au compilateur "considérez o d'avoir le type {}", tout comme dans mon exemple j'ai dit "considérez c pour avoir le type Animal". À cause de cela, le compilateur a explicitement été dit d'oublier qu'il travaille avec un Cat, donc il oublie que l'objet a une propriété .foo.

Il semble que l'algorithme de sous-typage structurel de flux oublie parfois des propriétés spécifiques à un certain sous-type. Est-ce que ce comportement est prévu ou est-ce que je viens juste de tomber dans un cas limite? Donc, pour répondre à cela, il ne le fait pas "occasionnellement", il le fait exactement quand vous lui dites de le faire. Le comportement est absolument destiné. Ceci est étrange car AFAIK un sous-type structurel peut généralement contenir des propriétés spécifiques tant qu'il inclut également toutes les propriétés requises de son supertype.

L'objet ne contient que la propriété, ce qui est bien 100%, mais vous avez explicitement effacé ces informations par la coulée de la valeur à un super-type.

+0

C'était avec certitude pas l'une de mes meilleures questions. Merci d'avoir pris le temps d'y répondre quand même! La vraie question est donc de savoir comment se comporte le flux lorsqu'il n'y a pas d'annotation explicite mais que le type doit être déduit, car un objet est renvoyé par une fonction dans une composition plus complexe. Y a-t-il aussi une perte d'information? En relation: [règle de subsomption] (https://news.ycombinator.com/item?id=13047934) – ftor

+1

Je me sens comme si j'avais besoin d'un exemple explicite, mais autant que je sache, il ne devrait pas y avoir d'information perdue dans inférence de type. – loganfsmyth