typescript ts2345传递{a:number}record<string, unknown>或record<string, never>,而不是分配

问题描述 投票:0回答:1
当使用该函数的一个类型

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

typescript
1个回答
0
投票
© www.soinside.com 2019 - 2025. All rights reserved.