oop - 如何使用介面取出物件的子集合?
假設我有這個類別和介面
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
}
答案#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;
}());
正如你所看到的,這些屬性並不是編譯後的輸出的一部分,因為類的成員僅會被添加到實例上,而不會添加到類上,所以即使是一個類也無法幫助你。
你可以使用裝飾器和元資料(這裡有更多相關內容),但對你的情境來說這聽起來有些過頭。
另一個更通用的 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"'
