0

我正在使用 ava (没有链接,因为我不允许使用超过 2 )进行测试,并且想要输入 ava 的测试上下文。它是在 ava 的定义文件中输入any的。

我特别想要的是打字稿编译器知道它属于以下测试t.context中的类型:{foo: number}

import test from 'ava'

test.beforeEach((t) => {
  t.context = { foo: 5 }
})

test('Is context typed', (t) => {
  // uncaught typo
  t.is(t.context.fooo, 5)
})

我试图使用声明合并来做到这一点,但它失败了TS2403: Subsequent variable declarations must have the same type. Variable 'context' must be of type 'any', but here has type '{ foo: number; }'.

declare module 'ava' {
    interface ContextualTestContext {
      context: {
        foo: number,
      }
    }
}

test.beforeEach((t) => {
  t.context = { foo: 5 }
})

test('Is context typed', (t) => {
  // uncaught ypo
  t.is(t.context.fooo, 5)
})

有没有办法做到这一点,而无需像这样一直投射上下文:

interface IMyContext {
  foo: number
}

test.beforeEach((t) => {
  t.context = { foo: 5 }
})

test('Is context typed', (t) => {
  const context = <IMyContext> t.context
  // caught typo
  t.is(context.fooo, 5)
})
4

2 回答 2

0

没有通用的方法来做到这一点。在您的特殊情况下,您可以创建一个新的TestContext,例如,而不是

export type ContextualTest = (t: ContextualTestContext) => PromiseLike<void> | Iterator<any> | Observable | void;

使用类似的东西

export type MyContextualTest<T> = (t : TestContext & {context : T}) => PromiseLike<void> ...

并声明你自己的test函数,它应该像这样与 Ava 兼容:

interface MyTestFunction<T> {
    (name : string, run : MyContextualTest<T>)
}

import {test as avaTest} from 'ava';
const test : MyTestFunction<IMyContext> = avaTest;

这主要是未经测试的,所以如果有一些问题,请告诉我。

于 2017-02-23T17:21:25.813 回答
0

下一个版本的 ava 可以输入上下文。然后你可以做这样的事情:

import * as ava from 'ava';

function contextualize<T>(getContext: () => T): ava.RegisterContextual<T> {
    ava.test.beforeEach(t => {
        Object.assign(t.context, getContext());
    });

    return ava.test;
}

const test = contextualize(() => {
    return { foo: 'bar' };
});

test.beforeEach(t => {
    t.context.foo = 123; // error:  Type '123' is not assignable to type 'string'
});

test.after.always.failing.cb.serial('very long chains are properly typed', t => {
    t.context.fooo = 'a value'; // error: Property 'fooo' does not exist on type '{ foo: string }'
});

test('an actual test', t => {
    t.deepEqual(t.context.foo.map(c => c), ['b', 'a', 'r']); // error: Property 'map' does not exist on type 'string'
});

如果您异步获取上下文,则需要contextualize相应地更改类型签名:

function contextualize<T>(getContext: () => Promise<T>): ava.RegisterContextual<T> {
    ava.test.beforeEach(async t => {
        Object.assign(t.context, await getContext());
    });

    return ava.test;
}

const test = contextualize(() => {
    const db = await mongodb.MongoClient.connect('mongodb://localhost:27017')

    return { db }
});

否则 TypeScript 编译器会认为t.context它是一个 Promise,尽管它不是

于 2017-03-16T11:13:05.693 回答