如何将javascript对象简化为仅包含来自接口的属性

如何将javascript对象简化为仅包含来自接口的属性,javascript,angularjs,typescript,Javascript,Angularjs,Typescript,使用typescript时,声明的接口可能如下所示: interface MyInterface { test: string; } class MyTest implements MyInterface { test: string; newTest: string; } 具有额外属性的实现可以如下所示: interface MyInterface { test: string; } class MyTest implements MyInterface { test

使用typescript时,声明的接口可能如下所示:

interface MyInterface {
  test: string;
}
class MyTest implements MyInterface {
  test: string;
  newTest: string;
}
具有额外属性的实现可以如下所示:

interface MyInterface {
  test: string;
}
class MyTest implements MyInterface {
  test: string;
  newTest: string;
}
示例(此处变量“reduced”仍包含属性“newTest”):

问题

一般来说,如何使“reduced”变量仅包含在“MyInterface”接口中声明的属性

为什么


在将“reduced”变量发送到rest服务之前,尝试将其与angular.toJson一起使用时会出现问题-toJson方法会转换newTest变量,即使在编译期间实例上无法访问该变量,这会使rest服务不接受json,因为它具有不应该存在的属性

在您的示例中,newTest属性不能通过reduced变量访问,因此这就是使用类型的目的。typescript带来类型检查,但它不操纵对象属性。

在您的示例中,newTest属性将无法通过reduced变量访问,因此这就是使用类型的目的。typescript带来类型检查,但它不操纵对象属性。

您是否仅尝试设置/分配界面上列出的属性?这样的功能在TypeScript中是不可用的,但是编写一个函数来执行您想要的行为非常简单

interface-IPerson{
名称:字符串;
}
类人实现IPerson{
名称:字符串=“”;
}
班级工作人员实施IPerson{
名称:字符串=“”;
位置:字符串=“”;
}
var jimStaff:员工={
名字:“吉姆”,
职位:“程序员”
};
变量jim:Person=newperson();
limitedAssign(jimStaff,jim);
console.log(jim);
函数限制分配(源:T,目标:S):无效{
用于(目标中的var prop){
if(源[prop]&&destination.hasOwnProperty(prop)){
目的地[prop]=源[prop];
}
}

}
是否仅尝试设置/分配界面上列出的属性?这样的功能在TypeScript中是不可用的,但是编写一个函数来执行您想要的行为非常简单

interface-IPerson{
名称:字符串;
}
类人实现IPerson{
名称:字符串=“”;
}
班级工作人员实施IPerson{
名称:字符串=“”;
位置:字符串=“”;
}
var jimStaff:员工={
名字:“吉姆”,
职位:“程序员”
};
变量jim:Person=newperson();
limitedAssign(jimStaff,jim);
console.log(jim);
函数限制分配(源:T,目标:S):无效{
用于(目标中的var prop){
if(源[prop]&&destination.hasOwnProperty(prop)){
目的地[prop]=源[prop];
}
}
}
一般来说,如何使“reduced”变量仅包含在“MyInterface”接口中声明的属性

由于TypeScript是结构化的,这意味着任何包含相关信息的内容都是类型兼容的,因此是可分配的

也就是说,TypeScript1.6将得到一个称为的概念。这将更容易捕捉清楚的打字错误(注意,新鲜度仅适用于对象文字):

一般来说,如何使“reduced”变量仅包含在“MyInterface”接口中声明的属性

由于TypeScript是结构化的,这意味着任何包含相关信息的内容都是类型兼容的,因此是可分配的

也就是说,TypeScript1.6将得到一个称为的概念。这将更容易捕捉清楚的打字错误(注意,新鲜度仅适用于对象文字):


TS 2.1具有对象扩展和静止功能,因此现在可以:

var my: MyTest = {test: "hello", newTest: "world"}

var { test, ...reduced } = my;

之后,reduced将包含除“test”之外的所有属性。

TS 2.1具有对象扩展和Rest,因此现在可以:

var my: MyTest = {test: "hello", newTest: "world"}

var { test, ...reduced } = my;
之后,reduced将包含除“test”之外的所有属性。

简单示例:

let all_animals = { cat: 'bob', dog: 'puka', fish: 'blup' };
const { cat, ...another_animals } = all_animals;
console.log(cat); // bob
简单的例子:

let all_animals = { cat: 'bob', dog: 'puka', fish: 'blup' };
const { cat, ...another_animals } = all_animals;
console.log(cat); // bob

这是不可能的。接口的原因是一个Typescript构造,而

因此,在运行时,没有什么可“处理”——没有可查询的属性

@jamesmoey的回答解释了一种实现预期结果的变通方法。 我使用的类似解决方案是将“接口”定义为一个类-

class MyInterface {
  test: string = undefined;
}
然后,您可以使用
lodash
从“接口”中拾取属性,以注入到对象中:

import _ from 'lodash';  //npm i lodash

const before = { test: "hello", newTest: "world"};
let reduced = new MyInterface();
_.assign(reduced , _.pick(before, _.keys(reduced)));
console.log('reduced', reduced)//contains only 'test' property


这是一个实用的解决方案,它为我提供了很好的服务,没有陷入关于它是否是接口和/或命名约定(例如,
IMyInterface
MyInterface
)的语义的泥潭,并且允许您模拟和单元测试,这是不可能的。接口的原因是一个Typescript构造,而

因此,在运行时,没有什么可“处理”——没有可查询的属性

@jamesmoey的回答解释了一种实现预期结果的变通方法。 我使用的类似解决方案是将“接口”定义为一个类-

class MyInterface {
  test: string = undefined;
}
然后,您可以使用
lodash
从“接口”中拾取属性,以注入到对象中:

import _ from 'lodash';  //npm i lodash

const before = { test: "hello", newTest: "world"};
let reduced = new MyInterface();
_.assign(reduced , _.pick(before, _.keys(reduced)));
console.log('reduced', reduced)//contains only 'test' property


这是一个实用的解决方案,对我很有帮助,它没有陷入关于它是否是接口和/或命名约定(例如,
IMyInterface
MyInterface
)的语义问题,并允许您模拟和单元测试另一种可能的方法:

正如其他答案所提到的,您无法避免在运行时做一些事情;TypeScript编译为JavaScript,主要是通过删除接口/类型定义、注释和断言。类型系统是,在需要的运行时代码中找不到您的
MyInterface
var test: MyTest = { test: "hello", newTest: "world" }

const reduced: MyInterface = pick(test, ...myTestKeys);

console.log(JSON.stringify(reduced)); // {"test": "hello"}
class MyClass {
  test: string;

  public static from(myClass: MyClass): MyClass {
    return {test: myClass.test};
  }
}
class MyTest extends MyClass {
  test: string;
  newTest: string;
}

const myTest: MyTest = {test: 'foo', newTest: 'bar'};
const myClass: MyClass = MyClass.from(myTest);