Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在TypeScript中为对象动态分配属性?_Typescript - Fatal编程技术网

如何在TypeScript中为对象动态分配属性?

如何在TypeScript中为对象动态分配属性?,typescript,Typescript,如果我想在Javascript中以编程方式为对象分配属性,我会这样做: var obj = {}; obj.prop = "value"; 但在TypeScript中,这会生成一个错误: 类型为“{}”的值上不存在属性“prop” 我应该如何为TypeScript中的对象分配任何新属性?尽管编译器抱怨它仍应按您的要求输出它。然而,这将起作用 var s = {}; s['prop'] = true; 您可以添加此声明以使警告静音 声明var obj:any; 或一气呵成: var obj

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

var obj = {};
obj.prop = "value";
但在TypeScript中,这会生成一个错误:

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


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

尽管编译器抱怨它仍应按您的要求输出它。然而,这将起作用

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

您可以添加此声明以使警告静音

声明var obj:any;
或一气呵成:

  var obj:any = {}
  obj.prop = 5;

我倾向于将
any
放在另一边,即
var foo:IFoo=

通过将任何新属性键入“any”来存储任何类型对象上的任何新属性:

var extend = <any>myObject;
extend.NewProperty = anotherObject;
var extendedObject = <any>myObject;
var anotherObject = <AnotherObjectType>extendedObject.NewProperty;
var extend=myObject;
extend.NewProperty=另一个对象;
稍后,您可以通过将扩展对象强制转换回“any”来检索它:

var extend = <any>myObject;
extend.NewProperty = anotherObject;
var extendedObject = <any>myObject;
var anotherObject = <AnotherObjectType>extendedObject.NewProperty;
var extendedObject=myObject;
var anotherObject=extendedObject.NewProperty;

当对象具有特定类型时,此解决方案非常有用。类似于将对象获取到其他源时

let user: User = new User();
(user as any).otherProperty = 'hello';
//user did not lose its type here.

最佳做法是使用安全键入,我建议您:

interface customObject extends MyObject {
   newProp: string;
   newProp2: number;
}

若要保留以前的类型,请将对象临时强制转换为任何

  var obj = {}
  (<any>obj).prop = 5;
var obj={}
(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;
var a=obj.prop;=>将生成一个编译器错误
变量b=(对象).prop;=>将5分配给b,没有错误;

要执行此操作,还有一个选项是作为集合访问属性:

var obj={};

obj['prop']=“值”为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' 
};
索引类型 可以将
obj
表示为
any
,但这违背了使用typescript的全部目的
obj={}
意味着
obj
是一个
对象
。将其标记为
any
毫无意义。为了实现所需的一致性,可以如下定义接口

interface LooseObject {
    [key: string]: any
}

var obj: LooseObject = {};
或者,为了使其紧凑:

var obj: {[k: string]: any} = {};
LooseObject
可以接受任何字符串作为键的字段和
any
类型作为值的字段

obj.prop = "value";
obj.prop2 = 88;
这个解决方案的真正优雅之处在于,您可以在接口中包含类型安全字段

interface MyType {
    typesafeProp1?: number,
    requiredProp1: string,
    [key: string]: any
}

var obj: MyType ;
obj = { requiredProp1: "foo"}; // valid
obj = {} // error. 'requiredProp1' is missing
obj.typesafeProp1 = "bar" // error. typesafeProp1 should be a number

obj.prop = "value";
obj.prop2 = 88;
记录
实用程序类型 更新(2020年8月):@transang在评论中提到了这一点

Record
是typescript中的一种实用程序类型。对于属性名称未知的键值对,它是一个更干净的选择。 值得注意的是,
Record
{[k:Keys]:Type}
的命名别名,其中
Keys
Type
是泛型。 在国际海事组织,这值得一提

作为比较

var obj: {[k: string]: any} = {};
变成

var obj: Record<string,any> = {}
虽然这回答了最初的问题,@GreeneCreations的回答可能会从另一个角度看待如何解决这个问题


要确保类型是
对象
(即键值对),请使用:


如果您使用的是Typescript,那么您可能希望使用类型安全性;在这种情况下,裸体对象和“any”被反向指示

最好不要使用对象或{},而是使用一些命名类型;或者,您可能正在使用具有特定类型的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:PropAble = getTheGivenObject();
k.props = "value for props";

可以通过以下方式将成员添加到现有对象中:

  • 拓宽类型(读:扩展/专门化接口)
  • 将原始对象强制转换为扩展类型
  • 将成员添加到对象
  • 接口IEnhancedPromise扩展了Promise{
    sayHello():void;
    }
    const p=承诺、决心(“彼得”);
    const enhancedPromise=p作为IEnhancedPromise;
    enhancedPromise.sayHello=()=>enhancedPromise.then(value=>console.info(“Hello”+value));
    //最终打印出“你好,彼得”
    enhancedPromise.sayHello();
    
    案例1:

    var car = {type: "BMW", model: "i8", color: "white"};
    car['owner'] = "ibrahim"; // You can add a property:
    
    案例2:

    var car:any = {type: "BMW", model: "i8", color: "white"};
    car.owner = "ibrahim"; // You can set a property: use any type
    

    我很惊讶没有一个答案引用Object.assign,因为每当我想到JavaScript中的“组合”时,我都会使用这种技术

    它在TypeScript中的工作方式与预期相同:

    interface IExisting {
        userName: string
    }
    
    interface INewStuff {
        email: string
    }
    
    const existingObject: IExisting = {
        userName: "jsmith"
    }
    
    const objectWithAllProps: IExisting & INewStuff = Object.assign({}, existingObject, {
        email: "jsmith@someplace.com"
    })
    
    console.log(objectWithAllProps.email); // jsmith@someplace.com
    
    优势

    • 始终键入安全性,因为您根本不需要使用
      任何
      类型
    • 使用TypeScript的聚合类型(在用AllProps
    声明
    对象的类型时由
    表示),这清楚地表明我们正在动态地合成一个新类型(即动态地)
    
    需要注意的事项

  • Object.assign有自己独特的方面(大多数经验丰富的JS开发人员都知道),在编写打字脚本时应该考虑这些方面。
    • 它可以以可变的方式或不可变的方式使用(我在上面演示了不可变的方式,这意味着
      现有对象
      保持不变,因此没有
      电子邮件
      属性。对于大多数函数式程序员来说,这是一件好事,因为结果是唯一的新变化)
    • Object.assign在拥有更平坦的对象时效果最佳。如果要组合两个包含可为空属性的嵌套对象,则最终可能会用未定义的属性覆盖truthy值。如果您注意Object.assign参数的顺序,您应该不会有问题

  • 因为您不能这样做:

    obj.prop = 'value';
    
    如果您的TS编译器和linter没有严格要求您,您可以编写以下代码:

    obj['prop'] = 'value';
    
    如果您的TS编译器或linter是严格的,那么另一个答案是typecast:

    var obj = {};
    obj = obj as unknown as { prop: string };
    obj.prop = "value";
    

    最简单的将是以下

    const obj = <any>{};
    obj.prop1 = "value";
    obj.prop2 = "another value"
    
    constobj={};
    obj.prop1=“值”;
    obj.prop2=“另一个值”
    
    您可以使用spread操作符基于旧对象创建新对象

    interface MyObject {
        prop1: string;
    }
    
    const myObj: MyObject = {
        prop1: 'foo',
    }
    
    const newObj = {
        ...myObj,
        prop2: 'bar',
    }
    
    console.log(newObj.prop2); // 'bar'
    
    TypeScript将推断原始对象的所有字段,VSCode将执行自动补全等操作。

    您可以使用:

    this.model = Object.assign(this.model, { newProp: 0 });
    
    试试这个:

    export interface QueryParams {
        page?: number,
        limit?: number,
        name?: string,
        sort?: string,
        direction?: string
    }
    
    然后使用它

    const query = {
        name: 'abc'
    }
    query.page = 1
    
    这里
    export interface QueryParams {
        page?: number,
        limit?: number,
        name?: string,
        sort?: string,
        direction?: string
    }
    
    const query = {
        name: 'abc'
    }
    query.page = 1
    
    function assign<T, U>(target: T, source: U): asserts target is T & U {
        Object.assign(target, source)
    }
    
    const obj = {};
    assign(obj, { prop1: "foo" })
    //  const obj now has type { prop1: string; }
    obj.prop1 // string
    assign(obj, { prop2: 42 })
    //  const obj now has type { prop1: string; prop2: number; }
    obj.prop2 // number
    
    //  const obj: { prop1: "foo", prop2: 42 }
    
    interface Example {
      a: string;
      b: number;
    }
    
    function getObject() {
      const object: Partial<Example> = {};
      object.a = 'one';
      object.b = 1;
      return object as Example;
    }
    
    interface Example {
      a: string;
      b: number;
    }
    
    function getObject() {
      const object = {} as Example;
      object.a = 'one';
      object.b = 1;
      return object;
    }
    
    <div *ngIf="$any(user).otherProperty">
       ...
       ...
    </div>