2017-02-23 110 views
0

我正在使用ava(无链接,因为我不允许使用超过2个)进行测试,并且想要输入ava的测试环境。这是typed as any in ava's definition file后续变量声明必须具有相同的类型。任何

我特别希望的是,打字稿编译器知道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) 
}) 

我试图用declaration merging要做到这一点,但它失败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) 
}) 

回答

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 } 
}); 

否则打字稿编译器会认为t.context是一种承诺,虽然它不是

0

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

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

使用类似

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

,并声明自己test功能,这应该是兼容的,阿瓦是这样的:

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

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

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

+1

@despairblue你能为你的用例提出一个问题吗?也许我们可以在'test()'签名中接受一个通用的。 –

+0

@MarkWubben谢谢,我在这里打开https://github.com/avajs/ava/issues/1291 – despairblue

+0

@FinnO在技术上起作用,但如果我想使用'test'函数本身定义的函数(比如' test.beforeEach')我将不得不重新定义所有的声明。其中大约有1700个。 – despairblue

相关问题