有没有一种方法可以动态地从属于接口的对象中提取成员(即不显式地再次指定它们),就像这样:
let subset = { ...someObject as ISpecific };
目前我得到了someObject碰巧拥有的所有成员。所以spread运算符在这里不起作用。有什么方法可以做到这一点吗?
示例:
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强制转换仅仅是编译器的提示,而不是运行时的真实的转换。
7条答案
按热度按时间3mpgtkmj1#
由于typescript接口在运行时不存在,我们不能使用它们来指导任何运行时行为,只是编译时的类型检查。然而,我们可以创建一个与接口具有相同属性的对象(例如,使用
true
类型的所有属性来简化初始化),并使编译器在此对象的字段比接口多或少时触发错误。我们可以使用这个对象作为我们提取哪些属性的指南:nwlls2ji2#
如果你想限制你 * 使用 * 的类型,你可以简单而安全地做到这一点:
这些属性仍然存在于
subset
上,但编译器会阻止你依赖它们,即subset.age
将在下面失败,尽管属性 does 仍然存在。你真的可以通过这样的解构来抛弃属性,危险在于你需要在
...subset
之前的列表中包括“所有我不想要的东西”。nwnhqdif3#
我遇到的另一个简单的选择是使用lodash的pick函数,它有点乏味,但工作做得很好。
首先,定义一个代表你的接口的类。你以后会需要它来轻松地创建这个类的对象。
然后假设这是您要从中提取数据的原始对象:
现在有趣的部分来了,基于类的新示例化获取
Specific
键的列表,并从原始对象中获取pick
这些成员。换句话说:
瞧!:)
cwdobuhd4#
很遗憾不是,你需要详细说明并重复这些部分。
mzaanser5#
@titian是正确的,typescript接口/类型在运行时不存在,但可执行代码DOES在编译时存在!
如果你不需要一个类,这里有一个更短,更少类型的解决方案,它采用一个类型或示例和一个简单的字符串数组作为键:
这种方法将保存您的击键时,它的时间来使用它:
但更重要的是,它可以防止您选择类型不允许的键。如果您想使用
pickSafely
来清理来自用户的数据或在通过网络发送数据库响应之前从数据库响应中删除字段,这很有用。这个解决方案的神奇之处在于使用Template Literal Types从普通Type动态生成文字类型的联合。
这并不能防止您将属性添加到
ObjectType
并忘记将其添加到keys
-可以将其视为一个白名单,该白名单本身由类型列入白名单;)下面是这段代码在VSCode中产生的类型错误:
ghhaqwfi6#
**可以使用装饰器实现(见最后的需求)。**只能与方法一起使用(复制属性get/set访问器只会产生其瞬时返回值,而不是访问器函数)。
kb5ga3dv7#
更新:这似乎不起作用,所以不是一个答案。
Object.create使用指定的原型创建一个新对象,但TypeScript强制转换只是对编译器的提示。它可能使用具体的类层次结构,然后引用原型,但这可能包含比接口声明的更多的实际成员。