为什么 Typescript 映射类型会引发编译错误

问题描述

我有以下代码Typescript Playground Link

class User {
    email?: string;
}

type FilterQuery<T> = {
    [P in keyof T]?:T[P];
}

interface IUserRepository<TUser extends User> {
    findOne(filter: FilterQuery<TUser>): TUser;
}

class UserService<TUser extends User> {
    constructor(private userRepository: IUserRepository<TUser>) {

    }

    getUser(email: string) {
        this.userRepository.findOne({ email: email });
    }
}

我收到以下编译错误

'{ email: string; 类型的参数}' 不能分配给参数 'FilterQuery' 类型。

我什至在 { email: email } 上得到了正确的自动完成,所以我不确定我做错了什么。

解决方法

问题在于泛型 TUser extends User。如果它只是 User 而没有泛型则没有错误。

当您允许 TUser 扩展为 User 时,您允许 TUseremail 的定义比仅 {{1} 更具体的可能性}}。

假设 string 实例的泛型 TUserUserService。这确实扩展了 { email: 'literalstring@gmail.com'; } 所以没问题。但是,如果您要调用 User,那么您将获得无效的 getUser('differentstring@gmail.com')。并非所有 FilterQuery 值在这里都有效。 string 是此实例的 'literalstring@gmail.com' 的唯一有效值。

如果没有正当理由使 FilterQuery 成为泛型类,则删除泛型并将您的存储库类型基于 UserService

(注意:我原以为将 User 的签名更改为 getUser 会在保持泛型的同时修复它,但它仍然给出错误,我无法真正解释原因) .