use
参数之一时,问题就会发生,因此我希望它可以用类型字符串的键和某种类型的某些推断值推断自定义条目。但实际上,我在尝试使用
MiddleWare<Record<string, unknown>>
函数时会遇到编译错误
例如,当尝试传递到类型参数的函数时,我会收到与中间件接口回调之一有关的错误:::
use
相关代码看起来像这样:
MiddleWare<{a: number}, {x: number}, TestEvents>
以及采用中间件参数的方法MiddleWare<Record<string, unknown>, {x: number}>>
在这里是用法的样子:
process
i我尝试修补
Types of property process are incompatible.
Type '(ctx: Context<{ a: number; }, TestEvents>) => { x: number; } | Promise<{ x: number; }>' is not assignable to type '(ctx: Context<Record<string, unknown>, TestEvents>) => { x: number; } | Promise<{ x: number; }>'.
Types of parameters ctx and ctx are incompatible.
Type Context<Record<string, unknown>, TestEvents> is not assignable to type Context<{ a: number; }, TestEvents>
Property 'a' is missing in type Context<Record<string, unknown>, TestEvents> but required in type { a: number; }
和export type MiddleWare<
TInput extends Record<string, unknown>,
TOutput extends Record<string, unknown>,
TEvents extends EventMap,
> = {
name: string
deps?: (keyof TInput & string)[]
provides: keyof TOutput & string
process: (ctx: Context<TInput, TEvents>) => Promise<TOutput> | TOutput
rollback?: (ctx: Context<TInput & TOutput, TEvents>) => Promise<void> | void
}
export const createPipeline = <
TEvents extends EventMap = {},
TInitial extends Record<string, unknown> = Record<string, unknown>,
>(): Pipeline<
TInitial,
Record<string, unknown>,
TEvents
> => {
const middlewares: MiddleWare<
Record<string, unknown>,
Record<string, unknown>,
TEvents
>[] = []
const eventSystem = createEventSystem<TEvents>()
return {
async execute(input) {
let ctx = createInitialContext(input, eventSystem)
const hookSystem = createHookSystem<typeof ctx, TEvents>()
try {
await hookSystem.trigger('before', ctx)
for (const mw of middlewares) {
// Type assertion for middleware compatibility
ctx = await processMiddleware(
mw as unknown as MiddleWare<typeof ctx, any, TEvents>,
ctx,
)
Object.freeze(ctx)
}
await hookSystem.trigger('after', ctx)
return ctx as Context<any, TEvents>
} catch (error) {
const errorCtx: Context<Record<string, unknown>, TEvents> = {
...ctx,
$error: error as Error,
$hooks: createHookSystem<
Record<string, unknown>,
TEvents
>(),
}
await hookSystem.trigger(
'error',
errorCtx as Context<any, TEvents>,
)
throw errorCtx
}
},
use<TNew extends Record<string, unknown>>(
mw: MiddleWare<Record<string, unknown>, TNew, TEvents>,
) {
middlewares.push(mw as MiddleWare<any, any, TEvents>)
return this as unknown as Pipeline<
TInitial, // try to tinker unknown / never
Record<string, unknown> & TNew,
TEvents
>
},
events: eventSystem,
hooks: createHookSystem<Record<string, unknown>, TEvents>(),
}
}
和// First middleware: adds property 'x'
// no issues no errors, context infers and looks fine, no any values etc
const mw1: MiddleWare<{ 'a': number }, { 'x': number }, TestEvents> = {
name: 'addX',
provides: 'x',
process: (ctx) => ({ ...ctx, 'x': ctx['a'] + 10 }),
}
// Second middleware: uses 'x' to produce property 'y'
// same situation here
const mw2: MiddleWare<{ a: number; x: number }, { y: number }, TestEvents> = {
name: 'addY',
deps: ['x'],
provides: 'y',
process: (ctx) => ({ ...ctx, y: ctx.x * 2 }),
}
const pipeline = createPipeline<TestEvents>()
// Use both middlewares in the pipeline.
// ! TS2345 !
pipeline
.use(mw1) // <{a: number},{x: number},TestEvents> not assignable to <Record<string, unknown>,...>
.use(mw2)
// Execute the pipeline.
const input = { a: 5 }
const result = await pipeline.execute(input)
函数首先实例化空值,然后为其分配新的类型,但它不起作用
通过添加辅助功能来创建中间件来解决它
never