2016-07-20 17 views
2

Dies ist eine SSCCE.dynamische Typprüfungen funktionieren nicht wie erwartet

Ich habe eine Karte Container-Klasse, wo eine interne Map auf Nachfrage mit dem ersten set Methode erstellt wird, aufgerufen wird:

// @flow 
'use strict'; 

class MapContainer { 

    map: ?Map<any, any>; 

    constructor() { 
     this.map=null; 
    } 

    set(key: any, value: any): ?any { 
     if (this.map===null) { 
      this.map = new Map(); 
     } 
     let prevValue: ?any; 
     if (this.map!=null) { // first check 
      prevValue = this.map.get(key); 
     } 
     if (this.map!=null) { // second check 
      this.map.set(key, value); 
     } 
     return prevValue; 
    } 
}  
exports.MapContainer = MapContainer; 

Der obige Code übergibt npm run flow ohne Warnungen.

Allerdings, wenn ich fusionieren die beiden if (this.map!=null) Kontrollen in einem:

// @flow 
'use strict'; 

class MapContainer { 

    map: ?Map<any, any>; 

    constructor() { 
     this.map=null; 
    } 

    set(key: any, value: any): ?any { 
     if (this.map===null) { 
      this.map = new Map(); 
     } 
     let prevValue: ?any; 
     if (this.map!=null) { // merged check 
      prevValue = this.map.get(key); 
      this.map.set(key, value); 
     } 
     return prevValue; 
    } 
}  
exports.MapContainer = MapContainer; 

& hellip; dann schlägt mit dem folgenden Nachrichtenfluss ausgeführt wird:

es6/map-container.js:19 
19:     this.map.set(key, value); 
       ^^^^^^^^^^^^^^^^^^^^^^^^ call of method `set`. Method cannot be called on possibly null value 
19:     this.map.set(key, value); 
       ^^^^^^^^ null 

es6/map-container.js:19 
19:     this.map.set(key, value); 
       ^^^^^^^^^^^^^^^^^^^^^^^^ call of method `set`. Method cannot be called on possibly undefined value 
19:     this.map.set(key, value); 
       ^^^^^^^^ undefined 

& hellip; das macht keinen Sinn, überhaupt als Zugang auf der Linie 19:

this.map.set(key,value)

& hellip;

if (this.map!=null)

Was gibt: wird noch durch die Prüfung abgedeckt?

Antwort

1

Das Problem ist, dass Aufruf an get Methode Verfeinerung ungültig machen kann. Was ist, wenn getthis.map bis null setzt? Flow hat keine Möglichkeit zu wissen, also nimmt er das Schlimmste an. Hier ist, was Sie tun können:

class MapContainer { 

    map: ?Map<any, any>; 

    constructor() { 
     this.map=null; 
    } 

    set(key: any, value: any): ?any {  
     if (!this.map) { 
      this.map = new Map(); 
     } 

     const map = this.map; 

     let prevValue: ?any; 
     if (this.map!=null) { 
      prevValue = map.get(key); 
      map.set(key, value); 
     } 
     return prevValue; 
    } 
}