代码之家  ›  专栏  ›  技术社区  ›  millimoose Tomasz Nurkiewicz

是否有一种类型安全的方法来表示函数在传递t时返回t类型的对象,而传递t时返回partial<t>类型的对象?

  •  2
  • millimoose Tomasz Nurkiewicz  · 技术社区  · 5 年前

    我正在编写函数来清理传递给我的CRUD操作的输入;例如,我不希望该操作能够创建或更新用户来设置一个表示无限制管理员的内部标志。

    我只是用罗达什的 _.pick 要仅从输入中投影已知属性,请执行以下操作:

    interface IUser {
        username: string;
        password: password;
    }
    
    interface IUserInternal {
        superuser: boolean;
    }
    
    function cleanUser(user: IUser): IUser {
        return _.pick(user, 'username', 'password');
    }
    
    function createUser(user: IUser) {
        db.create(cleanUser(user));
    }
    
    function updateUser(id: string, user: Partial<IUser>) {
        const old = db.get(id);
        db.update(id, {...old, ...cleanUser(user)});
    }
    

    我不能依赖于这里的类型检查,因为这是一个服务边界,在添加完整的验证之前,我现在想坚持快速和肮脏的东西。

    以上问题是最后一点:我打不到电话 cleanUser() 在一 Partial<IUser> 很明显。我也不能 CurraseServer() 拿回A 部分用户 ,因为我会丢失类型检查器,确保我选择了所有属性。实现本身将工作,因为pick将跳过在源对象中找不到的属性。

    我试着签名 cleanUser<T extends Partial<IUser>>(user: T): T 为了表示,我返回的是传入的相同内容,但刚告诉我返回值不能分配给 T . 我试图添加一个重载签名 cleanUser<Partial<IUser>>(user: Partial<IUser>) 但是,即使在传递给常规用户时,TS也会接收到这一点。

    有没有一种清晰的表达方式,或者我只是去“我知道我在做什么”并抑制类型错误?

    1 回复  |  直到 5 年前
        1
  •  2
  •   MTCoster    5 年前

    你可以使用 function overloads 为此:

    function cleanUser(user: IUser): IUser;
    function cleanUser(user: Partial<IUser>): Partial<IUser>;
    function cleanUser(user): any {
      return _.pick(user, 'username', 'password');
    }