avajs / flow-typed

Flow type definitions for AVA

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Flow TestInterface does not accept exact context type

gajus opened this issue · comments

Description

Flow TestInterface does not accept exact context type.

Test Source

// @flow

/* eslint-disable ava/use-test, no-unused-vars */

import untypedTest from 'ava';
import type {
  TestInterface
} from 'ava';

type ServerType = {||};

const test: TestInterface<ServerType> = untypedTest;

Error Message & Stack Trace

Cannot assign untypedTest to test because inexact object type [1] is incompatible with exact ServerType [2] in type
argument Context [3].

        test/integration.js
          9│
         10│ type ServerType = {||};
         11│
    [2]  12│ const test: TestInterface<ServerType> = untypedTest;
         13│

        node_modules/ava/index.js.flow
 [3][1] 461│ export interface TestInterface<Context = {}> {

Environment

Tell us which operating system you are using, as well as which versions of Node.js, npm, and AVA. Run the following to get it quickly:

node -e "var os=require('os');console.log('Node.js ' + process.version + '\n' + os.platform() + ' ' + os.release())"
ava --version
npm --version
Node.js v10.5.0
darwin 17.4.0
1.0.0-beta.6
6.1.0

There is something even more wrong with this:

// @flow

import untypedTest from 'ava';
import type {
  TestInterface
} from 'ava';

type ContextType = {
  server: ServerType
};

const test: TestInterface<ContextType> = untypedTest;
Cannot assign untypedTest to test because property server is missing in object type [1] but exists in ContextType [2] in
type argument Context [3].

        test/integration.js
         24│   server: ServerType
         25│ };
         26│
    [2]  27│ const test: TestInterface<ContextType> = untypedTest;
         28│
         29│ const SERVER_URL = 'http://127.0.0.1';
         30│

        node_modules/ava/index.js.flow
 [3][1] 461│ export interface TestInterface<Context = {}> {

Which Flow version is this? I'm pretty sure this worked when I wrote the definition, but I don't use Flow so I may have overlooked this.

Fixes to the definition are most welcome. Would be good to have a type-check regression test for this too.

I was able to work around this error by casting to any first:

import untypedTest from 'ava'

const test: TestInterface<{ directory: string }> = (untypedTest: any)

I'm using Flow v0.77.0 and played around for a while with the type definition, but haven't yet been able to find a fix.

Thanks for your comment @vinsonchuong. It prompted me to double-check our Flow recipe, and your solution is what's documented there: https://github.com/avajs/ava/blob/master/docs/recipes/flow.md#typing-tcontext

I'd still love if this wasn't necessary, of course.

@vinsonchuong Is there a more recent solution to this?

Things are working as expected and an error is thrown because untypedTest already has an invariant type argument provided. This works const test: TestInterface<{}> = untypedTest;, but for all other assignments it is unsound and untypedTest must be downcast to any at your discretion.

I believe an alternative would be to set any explicitly by default by exporting TypeInterface<any>. This should permit const test: TestInterface<MyContext> = untypedTest; and would not throw type errors for cases users aren't interested to have type soundness in their contexts like so:

import test from 'ava'

test.before('no type checking on context', t => {
  t.context.foo = 'bar'
})