有没有一种类型安全的方法来表示函数在传递T时返回类型T的对象,但是在传递时返回Partial <t>类型的对象呢?

时间:2019-02-11 16:20:42

标签: typescript

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

为此,我仅使用lodash的_.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>。我也无法使用cleanUser()并返回Partial<IUser>,因为那样我就失去了类型检查器,以确保我选择了所有属性。实现本身将起作用,因为pick只会跳过在源对象中找不到的属性。

我尝试制作签名cleanUser<T extends Partial<IUser>>(user: T): T以表示我返回的是被传递的相同内容,但只是告诉我返回值不可分配给T。我尝试添加一个过载签名cleanUser<Partial<IUser>>(user: Partial<IUser>),但即使传入普通用户,TS也会选择它。

是否有一种干净的表达方式,还是我只是去“我知道我在做什么”并抑制类型错误?

1 个答案:

答案 0 :(得分:2)

您可以为此使用function overloads

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