有没有办法从属于某个接口的对象中动态提取成员(即不再显式指定它们),如下所示:
let subset = { ...someObject as ISpecific };
目前我得到someObject碰巧拥有的所有成员。 所以扩散运营商在这里不起作用。有没有办法做到这一点?
示例:
interface ISpecific { A: string; B: string; }
class Extended implements ISpecific { public A: string = '1'; public B: string = '2'; public C: string = '3'; }
let someObject = new Extended();
let subset = { ...someObject as ISpecific };
console.log(subset); // -> { A, B, C } but want { A, B }
TypeScript强制转换只是编译器的提示,而不是运行时的实际转换。
答案 0 :(得分:8)
由于打字稿接口在运行时不存在,我们无法使用它们来指导任何运行时行为,只需编译时类型检查。但是,我们可以创建一个与接口具有相同属性的对象(例如,具有类型true
的所有属性以简化初始化),并且如果此对象具有任何更多或更少的字段,则使编译器触发错误。接口。我们可以使用此对象作为我们提取的属性的指南:
function extract<T>(properties: Record<keyof T, true>){
return function<TActual extends T>(value: TActual){
let result = {} as T;
for (const property of Object.keys(properties) as Array<keyof T>) {
result[property] = value[property];
}
return result;
}
}
interface ISpecific { A: string; B: string; }
const extractISpecific = extract<ISpecific>({
// This object literal is guaranteed by the compiler to have no more and no less properties then ISpecific
A: true,
B: true
})
class Extended implements ISpecific { public A: string = '1'; public B: string = '2'; public C: string = '3'; }
let someObject = new Extended();
let subset = extractISpecific(someObject);
答案 1 :(得分:1)
如果您想限制使用的类型,您可以通过以下方式安全地完成:
let subset = someObject as ISpecific;
属性仍然存在于subset
上,但编译器将阻止您依赖它们,即subset.age
将在下面失败,尽管属性 仍然存在。
interface ISpecific {
name: string;
}
const someObject = {
name: 'Fenton',
age: 21
};
let subset = someObject as ISpecific;
console.log(subset.age);
你可以通过这样的解构来真的抛弃属性,危险的是你需要在...subset
之前的列表中包含“我不想要的所有东西”。 / p>
interface ISpecific {
name: string;
}
const someObject = {
name: 'Fenton',
age: 21
};
let { age, ...subset } = someObject;
console.log(JSON.stringify(someObject));
console.log(JSON.stringify(subset));
答案 2 :(得分:0)
可以使用装饰器来实现(参见最后的要求)。 它只能与方法一起使用(复制属性get / set accessor只产生其瞬时返回值,而不是访问器函数)。
File ID: 1kIDop9cX5CvL5jxxxxxxxxxxxxyP
(这需要在tsconfig.json和ES5目标中使用compilerOption&#34; experimentalDecorators&#34;:true,http://www.typescriptlang.org/docs/handbook/decorators.html处有更多信息)
答案 3 :(得分:0)
不幸的是,您不需要指定并重复这些部分。
export interface Machine {
id: string;
name: string;
logo: string;
location: Location;
products: Item[];
restriction: string;
categories: string[];
star: number;
distance: number;
}
export interface MachineIdentification {
id: string;
name: string;
logo: string;
location: Location;
}
//Object Destructuring fat object in parts
const {id, name, logo, location} = machine;
//Compose a ligth object from parts and apply interface type
const mi: MachineIdentification = {id, name, logo, location};
答案 4 :(得分:-1)
更新:这似乎不起作用,所以不是答案。
owner = permissionsList.Permissions.FirstOrDefault(f => f.Role.ToLowerInvariant() == "owner")?.DisplayName;
Object.create使用指定的原型创建一个新对象,但TypeScript强制转换仅仅是编译器的提示。它可能使用具体的类层次结构,然后引用原型,但这可能包括比接口声明更多的实际成员。