如何使用接口获取对象的子集?

Bos*_*sak 6 oop interface mass-assignment typescript typescript2.0

假设我有这个类和接口

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

interface IUser {
    name: string;
    age: number;
}
Run Code Online (Sandbox Code Playgroud)

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

const data = {
    name: "John",
    age: 25,
    isAdmin: true
}
Run Code Online (Sandbox Code Playgroud)

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

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

我的问题是如何在 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
}
Run Code Online (Sandbox Code Playgroud)

Nit*_*mer 3

没有比以下更好的方法了:

function subset(obj: IUser) {
    return {
        name: obj.name,
        age: obj.age
    }
}
Run Code Online (Sandbox Code Playgroud)

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

您可以使用一个在编译过程中“幸存”的类,但是

class IUser {
    name: string;
    age: number;
}
Run Code Online (Sandbox Code Playgroud)

编译为:

var IUser = (function () {
    function IUser() {
    }
    return IUser;
}());
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,属性不是编译输出的一部分,因为类成员仅添加到实例而不是类中,因此即使是类也无法帮助您。

您可以使用装饰器和元数据(更多内容请参见此处),但这对于您的场景来说听起来有点过分了。

更通用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"'
Run Code Online (Sandbox Code Playgroud)