2017-02-23 1 views
0

Ich verwende Ava (kein Link, da ich nicht mehr als 2 verwenden darf) zum Testen und möchte den Testkontext von Ava eingeben. Es ist typed as any in ava's definition file.Nachfolgende Variablendeklarationen müssen denselben Typ haben. any

Was ich speziell will, ist, dass das Typoskript Compiler weiß, dass t.context vom Typ {foo: number} im folgenden Test:

import test from 'ava' 

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

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

Ich versuchte declaration merging zu verwenden, um dies zu tun, aber es funktioniert nicht mit 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) 
}) 

gibt es eine Möglichkeit, dies zu tun, ohne den Kontext wie so die ganze Zeit zu Gießen:

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

Antwort

0

Die Eingabe des Kontexts ist mit der nächsten Version von ava möglich. Dann können Sie etwas tun:

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

Wenn Sie erwerben Ihren Kontext asynchron müssen Sie die Art Signatur von contextualize entsprechend ändern:

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

Ansonsten Typoskript Compiler denken t.context ein Versprechen ist, obwohl es nicht ist

0

Es gibt keine allgemeine Möglichkeit, dies zu tun. In Ihrem speziellen Fall könnten Sie eine neue TestContext, z. statt

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

Verwendung so etwas wie

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

und erklären, um Ihre eigene test Funktion, die Ava wie dies kompatibel sein sollte:

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

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

Diese meist nicht getestet ist, so Wenn es Probleme gibt, lass es mich wissen.

+1

@despairblue könnten Sie ein Problem für Ihren Anwendungsfall auslösen? Vielleicht können wir ein Generikum in der 'test()' Signatur akzeptieren. –

+0

@MarkWubben Danke, ich öffnete es hier https://github.com/avajs/ava/issues/1291 – despairblue

+0

@FinnO, das technisch funktioniert, aber wenn ich die Funktionen verwenden will, die auf der 'Test'-Funktion selbst definiert sind (wie' test.beforeEach') Ich müsste alle Deklarationen neu definieren. Es gibt ungefähr 1700 von ihnen. – despairblue

Verwandte Themen