flow icon indicating copy to clipboard operation
flow copied to clipboard

flow fails to report error for map key value structure when dynamic keys are used and the key argument is typed

Open gdanov opened this issue 6 years ago • 5 comments
trafficstars

here's the live example

and bellow is the code. What seems to be the case is that (correctly) typed dynamic key value switches off the validation of the value for literals used in return or initialization only. untyped key value works as expected. Assignment a[id] = {id:'zz'} works as expected and throws error.

// @flow

type Struct = {
  [id: string] : {id: string, deps: Array<string>}
}

let id : string = 'iidd';
let untypedId = 'iidd';

// success
// $ExpectError
let a : Struct = {'abc': {id: 'xxx'}};

let b : Struct = {};
// success
// $ExpectError
b['abc'] = {id: 'xx'};

// success
// $ExpectError
b[id] = {id: 'xx'};

// --FAIL--
function testA(): Struct{
  // $ExpectError
  return {[id]: {id: 'zz'}}
}
a = testA();

function testAB(): Struct{
  // success
  // $ExpectError
  return {[untypedId]: {id: 'zz'}}
}

// --FAIL--
function testAC(): Struct{
  let res = {[id]: {id: 'zz'}};
  // $ExpectError
  return res;
}
a = testAC();

function testAD(): Struct{
  let res = {[untypedId]: {id: 'zz'}};
  // success
  // $ExpectError
  return res;
}

gdanov avatar Dec 11 '18 12:12 gdanov

refines #2928

gdanov avatar Dec 11 '18 12:12 gdanov

and #1971

gdanov avatar Dec 11 '18 12:12 gdanov

As I keep trying to figure out the safe boundaries, I did some experimenting with immutable's Map. The schema is similar to the example above, the weirdness again manifests itself only when initializing something with incompatible literal.


function testE (idx: string) : Map<string, DepsUnit> {
  // success, detects errors
  // $ExpectError
  return Map ({'abc': {id:'x'}})
}

function testEA (idx) : Map<string, DepsUnit> {
  // FAIL
  return Map ({[idx]: {id:'x'}})
}
// $ExpectError
testEA ('abc');
// fail
testEA (123);

function testEB (idx: string) : Map<string, DepsUnit> {
  // FAIL
  return Map ({[idx]: {id:'x'}})
}
// fail
testEB ('abc');
// $ExpectError
testEB (123);

function testEC (idx: string) : Map<string, DepsUnit> {
  // success
  // $ExpectError
  return Map ({}).set(idx, {id:'x'});
}

function testECC (idx) : Map<string, DepsUnit> {
  // success
  // $ExpectError
  return Map ({}).set(idx, {id:'x'});
}

gdanov avatar Dec 11 '18 13:12 gdanov

Same here

// @flow strict

type StaticKey = {|
  staticKey: string,
|};

const staticKeyObject: StaticKey = {
  staticKey: 'Haha',
};

type DynamicKey = {|
  [key: number]: string,
|};

const dynamicKeyObjectKO: DynamicKey = {
  [1]: "Just a string",
  // Error is expected here but none received
  [8]: 1,
};

// Error well received in that case
dynamicKeyObjectKO[1] = 2;

Or live example [HERE]

When could you have it fixed please ? We use that a lot for our normalized Redux states Thanks a lot !

LaurentRos avatar Nov 22 '19 16:11 LaurentRos

Is there a workaround for this? Can I somehow force cast a variable to be untyped?

maartenschumacher avatar Feb 01 '21 10:02 maartenschumacher