类型参数不可分配给类型参数

Mar*_*ouw 5 typescript

下面的代码块是从一个更大的应用程序中删除的,以说明什么是破坏性的......如果我忽略错误,代码本身执行得很好。只是类型提示不喜欢它,不知道为什么。

但是,我确实相信这与该Omit类型有关。

我遇到了这个错误:

Argument of type '{ avatar: string; height: number; width: number; } & Pick<P & IInputProps, Exclude<keyof P, "firstName" | "lastName" | "avatar">>' is not assignable to parameter of type 'WrappedType<P>'.
    Type '{ avatar: string; height: number; width: number; } & Pick<P & IInputProps, Exclude<keyof P, "firstName" | "lastName" | "avatar">>' is not assignable to type 'P'.
Run Code Online (Sandbox Code Playgroud)

代码是(或要点):

type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;

interface FunctionComponent<P = {}> {
    (props: P, context?: any): string;
}

// Our component props types
interface IInputProps {
    firstName: string;
    lastName: string;
    avatar: string;
}

interface ISubProps {
    width: number;
    height: number;
}

// The helper type that takes an abstract prop type, adds the downstream ISubProps + a type that's based on our IInputProps
type WrappedType<P extends object = {}> = P &
    ISubProps &
    Omit<IInputProps, 'firstName' | 'lastName'>;

type SubComponent<P> = FunctionComponent<WrappedType<P>>;
type WrappedComponent<P> = FunctionComponent<P & IInputProps>;

function factory<P extends object = {}>(
    Component: SubComponent<P>,
): WrappedComponent<P> {

    // The props here are of type P & IInputProps
    return ({ lastName, firstName, avatar, ...rest }) => {
        const restString = Object.entries(rest)
            .map(([key, value]) => `${key}: ${value}`)
            .join('\n');

        // -- THIS BIT DOESNT WORK
        // Component's types are ISubProps + IInputProps (-firstName, -lastName) + P
        const componentResponse = Component(
            {
                avatar,
                height: 10,
                width: 20,
                ...rest,
            },
        );
        // -- TO HERE

        return `FirstName: ${firstName}\nLastName: ${lastName}\n${restString}\n\n--BEGIN--\n${componentResponse}\n--END--`;
    };
}


// Example impl
const test = factory<{ foo: string }>(props => {
    return `hello: ${props.foo}, you have the avatar of ${
        props.avatar
        } with height ${props.height} and width ${props.width}`;
})({
    firstName: 'firstName',
    lastName: 'lastName',
    avatar: 'avatar',
    foo: 'foo',
});

console.log(test);
Run Code Online (Sandbox Code Playgroud)

Tit*_*mir 5

问题是 Typescript 在包含未绑定类型参数的映射和条件类型上可以执行的数学运算非常有限(例如P在您的情况下)。

尽管这对我们来说似乎是显而易见的,但编译器无法弄清楚如果您lastName, firstName, avatar从 中删除 则P & { firstName: string; lastName: string; avatar: string; }得到P. 只要参数P在那里,编译器就不会尝试解析 的类型rest,而是将其余类型键入为Pick<P & IInputProps, Exclude<keyof P, "lastName" | "firstName" | "avatar">>

这里没有安全的方法来帮助编译器,您只需使用类型断言让编译器知道rest将是P

const componentResponse = Component({
    avatar,
    height: 10,
    width: 20,
    ...(rest as P),
}); 
Run Code Online (Sandbox Code Playgroud)