Flow: Any class type is consider a subtype of a generic indexer

Created on 11 Aug 2017  路  2Comments  路  Source: facebook/flow

Am I missing something, or is this a case where flow's analysis is unsound?

function test<T>(input: {[string]: T}) {}

class Foo {
  n: number;
  b: boolean;
}

test(new Foo);

https://flow.org/try/#0GYVwdgxgLglg9mABFApgZygHgCoD4AUMYADiFAFyIDeA2hgE5EDmAupdgL4CU1HAUHwgAbAIZo0iAGJw41PokRhKYEAFsARinoBueYnWV1MoShFhd-Pqgz4wKAO5SZXbUA

When Foo is an equivalent object type, it's (correctly) an error:

function test<T>(input: {[string]: T}) {}

type Foo = {
  n: number;
  b: boolean;
}

const foo: Foo = {n: 0, b: true};
test(foo);

https://flow.org/try/#0GYVwdgxgLglg9mABFApgZygHgCoD4AUMYADiFAFyIDeA2hgE5EDmAupdgL4CU1HAUHygBPYikQAxOHEQBean0SIwlMCAC2AIxT0A3AsQbKGqQBsUAQzB7+fCAgyJgUypOlyqyxAAYANAcpQ9CAoHHqoGPhOcFw6QA

object model soundness bug

Most helpful comment

Simpler example:

class Foo {
  n: number;
}

var x: { [string]: string } = new Foo;

It seems that class properties are simply ignored, the same with interface.

All 2 comments

To more obviously see why it's problematic, the first case was reduced from something similar to:

function eachValue<T>(input: {[string]: T}, fn: (T) => void) {
  for (const k in input) {
    fn(input[k]);
  }
}

class Foo {
  n: number;
  b: boolean;
}

eachValue(new Foo, (n: number) => {});

https://flow.org/try/#0GYVwdgxgLglg9mABAUwIYQBYDVUBsTIA8AKgHwAUMYADiFAFyIDeA2gM5QBOVA5gLqNiAXwA0iYGEbliASkQBeUogBucGABM5TAFCJxcTonIQEHRAGtEVKzTpbde8WEq2oLc3xkBuB0O1-tCFxUNjZEADE4OGYHSUQwEABbACNkTh89ZMZkqNw0MB8AtEwcfGRyMGQAdwiosQrGBJS0uUVmIW8gA

Simpler example:

class Foo {
  n: number;
}

var x: { [string]: string } = new Foo;

It seems that class properties are simply ignored, the same with interface.

Was this page helpful?
0 / 5 - 0 ratings