后续的变量声明必须具有相同的类型。任何
Subsequent variable declarations must have the same type. any
我正在使用 ava(没有 link,因为我不允许使用超过 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)
})
没有通用的方法可以做到这一点。在您的特殊情况下,您可以创建一个新的 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;
这大部分是未经测试的,所以如果有任何问题,请告诉我。
下一个版本的 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,尽管它不是
我正在使用 ava(没有 link,因为我不允许使用超过 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)
})
没有通用的方法可以做到这一点。在您的特殊情况下,您可以创建一个新的 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;
这大部分是未经测试的,所以如果有任何问题,请告诉我。
下一个版本的 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,尽管它不是