如何推断打字稿中泛型参数的泛型类型参数?

问题描述 投票:0回答:1

我有一个代表我的应用程序中的操作的类型:

type Operation<A, B> = {
    execute: (data: A) => B;
};

操作如下所示:

const op = {
    execute: (data: string) => {
        return data;
    },
};

我正在尝试创建一个抽象来装饰这个操作。添加装饰应保留任何先前添加的字段。例如,当我想通过事务处理来增强操作时:

export const wrapInTransaction = <A, B, O extends Operation<A, B>>(
   { execute, ...rest}: O 
): O => {
    const wrappedExecute = (data: A) =>
    {
        // add transaction logic here
        return execute(data)
    }        
    return {
        ...rest,
        execute: wrappedExecute,
    } as O;
}

我接受

Operation
的子类型,而不是通用
Operation<A, B>
。我的问题是这不起作用:

const wrapped = wrapInTransaction(op);

// Argument of type '{ execute: (data: string) => string; }' is not assignable to parameter // of type 'Operation<unknown, unknown>'.
//   Types of property 'execute' are incompatible.
//     Type '(data: string) => string' is not assignable to type '(data: unknown) => unknown'.
//       Types of parameters 'data' and 'data' are incompatible.
//         Type 'unknown' is not assignable to type 'string'

因为

O
的类型未被推断出来。我可以以某种方式构造
O
的默认值来推断
A
B
吗?

typescript typescript-generics type-inference
1个回答
0
投票

我建议简化通用性。鉴于它仅将

O
应用于参数
{ execute, ...rest}: O
,它只能推断
O
。虽然推导
A
B
对于人类来说是微不足道的,但我们可以使用此处记录的
infer
关键字严格地完成:条件类型,以帮助我们获得
A
B
。请注意,它实际上不能在泛型中,否则它是循环类型依赖。

// VV this works as well
// type DataFromOperation<T> = T extends Operation<infer A, unknown> ? A : unknown
type DataFromOperation<T extends Operation<unknown, unknown>> = T extends Operation<infer A, unknown> ? A : unknown

export const wrapInTransaction = <O extends Operation<any, any>>(
   { execute, ...rest}: O 
): O => {
    const wrappedExecute = (data: DataFromOperation<O>) =>
    {
        // add transaction logic here
        return execute(data)
    }        
    return {
        ...rest,
        execute: wrappedExecute,
    } as O;
}

在 TS Playground 观看

© www.soinside.com 2019 - 2024. All rights reserved.