【问题标题】:How to take a subset of an object using an interface?如何使用接口获取对象的子集?
【发布时间】:2017-08-19 02:14:20
【问题描述】:

假设我有这个类和接口

class User {
    name: string;
    age: number;
    isAdmin: boolean;
}

interface IUser {
    name: string;
    age: number;
}

然后我从某个地方得到这个 json 对象

const data = {
    name: "John",
    age: 25,
    isAdmin: true
}

我想使用IUser 子集data 并像这样删除isAdmin 属性

let user = subset<IUser>(data);
// user is now { name: "John", age: 25 }
// can safely insert user in the db

我的问题是如何在 TypeScript 中实现该功能?

function subset<T>(obj: object) {
    // keep all properties of obj that are in T
    // keep, all optional properties in T
    // remove any properties out of T
}

【问题讨论】:

    标签: oop typescript interface typescript2.0 mass-assignment


    【解决方案1】:

    没有比这更好的方法了:

    function subset(obj: IUser) {
        return {
            name: obj.name,
            age: obj.age
        }
    }
    

    typescript 接口在运行时不存在(即调用subset 时),因此您无法使用IUser 接口来了解哪些属性需要哪些不需要。

    你可以使用一个在编译过程中“存活”的类但是

    class IUser {
        name: string;
        age: number;
    }
    

    编译为:

    var IUser = (function () {
        function IUser() {
        }
        return IUser;
    }());
    

    如您所见,属性不是编译输出的一部分,因为类成员仅添加到实例而不添加到类,因此即使是类也无济于事。

    您可以使用装饰器和元数据 (more on that here),但这对于您的场景来说听起来有点过头了。

    更通用的subset 函数的另一个选项是:

    function subset<T>(obj: T, ...keys: (keyof T)[]) {
        const result = {} as T;
    
        keys.forEach(key => result[key] = obj[key]);
        return result;
    }
    let user1 = subset(data, "name", "age");
    let user2 = subset(data, "name", "ag"); // error: Argument of type '"ag"' is not assignable to parameter of type '"name" | "age" | "isAdmin"'
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-02
      • 2016-10-09
      • 2013-08-29
      • 2020-08-08
      • 2020-01-12
      相关资源
      最近更新 更多