如果我想在Javascript中以编程方式将一个属性分配给一个对象,我会这样做:

var obj = {};
obj.prop = "value";

但在TypeScript中,这会产生一个错误:

属性“prop”在类型为“{}”的值上不存在

我应该如何在TypeScript中分配任何新属性给对象?


当前回答

如果你正在使用Typescript,你可能想要使用类型安全;在这种情况下,naked Object和'any'是相反的。

最好不要使用Object或{},而是使用一些命名类型;或者您可能正在使用具有特定类型的API,您需要使用自己的字段进行扩展。我发现这个方法很有效:

class Given { ... }  // API specified fields; or maybe it's just Object {}

interface PropAble extends Given {
    props?: string;  // you can cast any Given to this and set .props
    // '?' indicates that the field is optional
}
let g:Given = getTheGivenObject();
(g as PropAble).props = "value for my new field";

// to avoid constantly casting: 
let k = getTheGivenObject() as PropAble;
k.props = "value for props";

其他回答

尽管编译器抱怨它仍然应该按照你的要求输出它。然而,这是可行的。

const s = {};
s['prop'] = true;

若要保留先前的类型,请将对象临时转换为any

  var obj = {}
  (<any>obj).prop = 5;

新的动态属性只有在使用强制转换时才可用:

  var a = obj.prop; ==> Will generate a compiler error
  var b = (<any>obj).prop; ==> Will assign 5 to b with no error;

在TypeScript中动态地为对象分配属性。

你只需要像这样使用typescript接口:

interface IValue {
    prop1: string;
    prop2: string;
}

interface IType {
    [code: string]: IValue;
}

你可以这样使用它

var obj: IType = {};
obj['code1'] = { 
    prop1: 'prop 1 value', 
    prop2: 'prop 2 value' 
};

可以使用展开操作符在旧对象的基础上创建新对象

interface MyObject {
    prop1: string;
}

const myObj: MyObject = {
    prop1: 'foo',
}

const newObj = {
    ...myObj,
    prop2: 'bar',
}

console.log(newObj.prop2); // 'bar'

TypeScript会推断出原始对象的所有字段,VSCode会自动补全,等等。

唯一完全类型安全的解决方案是这个,但是有点啰嗦,并且迫使您创建多个对象。

如果你必须先创建一个空对象,那么从这两个解决方案中选择一个。记住,每次你使用as,你就失去了安全。

安全解决方案

对象类型在getObject中是安全的,这意味着对象。A的类型为字符串| undefined

interface Example {
  a: string;
  b: number;
}

function getObject() {
  const object: Partial<Example> = {};
  object.a = 'one';
  object.b = 1;
  return object as Example;
}

短期解决方案

对象类型在getObject中是不安全的,这意味着对象。即使在赋值之前,A的类型也是string。

interface Example {
  a: string;
  b: number;
}

function getObject() {
  const object = {} as Example;
  object.a = 'one';
  object.b = 1;
  return object;
}