TypeScript에서 객체에 속성을 동적으로 할당하려면 어떻게합니까?


359

프로그래밍 방식으로 Javascript의 객체에 속성을 할당하려면 다음과 같이하십시오.

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

그러나 TypeScript에서는 다음과 같은 오류가 발생합니다.

'prop'특성이 '{}'유형의 값에 존재하지 않습니다.

TypeScript에서 객체에 새로운 속성을 할당하려면 어떻게해야합니까?


1
참고로 당신이 그것을 따르고 싶다면 이것과 관련된 토론열었 습니다.
joshuapoehls

답변:


455

로 표시 obj하는 것이 가능 any하지만 타입 스크립트 사용의 전체 목적을 상실합니다. obj = {}암시 obj입니다 Object. any의미가없는 것으로 표시하십시오 . 원하는 일관성을 달성하기 위해 인터페이스를 다음과 같이 정의 할 수 있습니다.

interface LooseObject {
    [key: string]: any
}

var obj: LooseObject = {};

또는 컴팩트하게 만들기 :

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

LooseObject모든 문자열이있는 필드를 키로, any유형을 값으로 사용할 수 있습니다.

obj.prop = "value";
obj.prop2 = 88;

이 솔루션의 진정한 우아함은 인터페이스에 typesafe 필드를 포함 할 수 있다는 것입니다.

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;

이것은 원래의 질문에 대답하면서, 대답 여기 @GreeneCreations으로이 문제를 접근하는 방법에 대해 다른 관점을 줄 수 있습니다.


13
나는 이것이 최선의 해결책이라고 생각합니다. 나는 질문 에이 같은 인덱스 속성이 TypeScript에서 아직 구현되지 않았다고 생각했다.
피터 올슨

Error
Wayou

@Wayou Error 및 Array와 같은 기본 객체는 Object에서 상속됩니다. 따라서 LooseObject오류가 발생할 수 있습니다.
Akash Kurian Jose

객체에 특정 (동적) 속성이 있는지 확인할 수 있습니까?
phhbr

1
이 느슨한 객체의 경우 getter-setter 형식으로 어떻게 작성합니까?
JokingBatman

81

아니면 한 번에 :

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

41
TypeScript any를 사용하기 위해 많은 것들을 캐스팅해야한다면 요점은 무엇입니까 ? 내 코드에서 추가 노이즈가 발생합니다 .. : /
AjaxLeung

16
@AjaxLeung 당신이 그렇게해야한다면, 당신은 그것을 잘못 사용하고 있습니다.
Alex

2
객체의 이전 유형을 유지하는 위의 추가 편집을 참조하십시오.
Andre Vianna

6
@AjaxLeung 당신은 매우 드물게 캐스팅해야 any합니다. TypeScript는 컴파일 타임에 (잠재적) 오류를 포착하는 데 사용됩니다. any오류를 음소거 하려고 캐스팅하면 입력 기능이 손실되고 순수한 JS로 돌아갈 수 있습니다. anyTS 정의를 작성할 수없는 코드를 가져 오거나 JS에서 TS로 코드를 마이그레이션하는 동안 코드를 가져 오는 경우에만 이상적으로 사용해야합니다.
Precastic

63

나는 any다른면 에 넣는 경향이 있습니다. 즉 var foo:IFoo = <any>{};이와 같은 것은 여전히 ​​유형 안전합니다.

interface IFoo{
    bar:string;
    baz:string;
    boo:string;     
}

// How I tend to intialize 
var foo:IFoo = <any>{};

foo.bar = "asdf";
foo.baz = "boo";
foo.boo = "boo";

// the following is an error, 
// so you haven't lost type safety
foo.bar = 123; 

또는 이러한 특성을 선택 사항으로 표시 할 수 있습니다.

interface IFoo{
    bar?:string;
    baz?:string;
    boo?:string;    
}

// Now your simple initialization works
var foo:IFoo = {};

온라인으로 사용해보십시오


5
타입 안전을 유지하는 유일한 솔루션 인 +1 나중에 버그를 물지 않도록 옵션이 아닌 모든 속성을 직접 입력하십시오.
Aidiakapi

이것이 실제로 작동합니까? 컴파일 한 후에도 여전히 자바 스크립트에 <any> {}가 있습니다.
bvs

4
I still have <any>{그런 다음 컴파일하지 않았습니다. 타이프 라이터는 발광에 그것을 제거하는 것
basarat

4
요즘 var foo: IFoo = {} as any선호됩니다. 타입 캐스팅을위한 구식 구문은 TSX (Typescript-ified JSX)와 충돌했습니다.

51

이 솔루션은 객체에 특정 유형이있을 때 유용합니다. 다른 소스에 객체를 가져올 때와 같습니다.

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

7
이것은 일회성 할당에 대한 올바른 솔루션입니다.
soundly_typed

이 답변은 페이스 북 로그인을 위해 객체에 속성을 추가해야했기 때문에 저에게 효과적 이었습니다. TypeScript 에서 as 키워드를 처음 사용 했습니다.
AlanObject

33

컴파일러는 불평하지만 여전히 원하는대로 출력해야한다고 불평합니다. 그러나 이것은 효과가 있습니다.

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

2
예, 이것은 실제로 유형 스크립트 방식이 아니며 지능이 느슨합니다.
pregmatch

25

그에 대한 또 다른 옵션은 컬렉션으로 속성에 액세스하는 것입니다.

var obj = {};
obj['prop'] = "value";


2
이것이 가장 간결한 방법입니다. Object.assign(obj, {prop: "value"})ES6 / ES2015에서 작동합니다.
Charles

9

JavaScript의 "composition"에 대해 생각할 때마다 사용하는 기술이기 때문에 Object.assign을 참조하는 답변이 없다는 것에 놀랐습니다.

그리고 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

장점

  • 사용할 필요가 없으므로 any 전혀 유형을
  • TypeScript의 집계 유형 ( &의 유형을 선언 할 때 표시됨 objectWithAllProps)을 사용하여 새 유형을 즉석에서 (즉 동적으로) 작성하고 있음을 명확하게 전달합니다.

알아야 할 사항

  1. Object.assign은 TypeScript를 작성할 때 고려해야 할 고유 한 측면 (가장 경험이 많은 JS 개발자에게 잘 알려진)을 가지고 있습니다.
    • 그것은 변경 가능한 방식으로 또는 불변의 방식으로 사용될 수 있습니다 (위의 불변의 방법을 보여줍니다. 즉, existingObject그대로 유지되므로email 속성 . 대부분의 함수형 프로그래머에게는 그 결과가 좋았습니다. 유일한 새로운 변화).
    • 더 평평한 객체가있을 때 Object.assign이 가장 효과적입니다. 널 입력 가능 특성을 포함하는 두 개의 중첩 된 오브젝트를 결합하는 경우, 정의되지 않은 값으로 정의 된 값을 겹쳐 쓸 수 있습니다. Object.assign 인수의 순서를 조심하면 괜찮을 것입니다.

나에게 데이터를 표시하기 위해 이것을 사용해야하는 경우에는 잘 작동하는 것처럼 보이지만 수정 된 유형의 항목을 배열에 추가 해야하는 경우 너무 잘 작동하지 않는 것 같습니다. 나는 객체를 동적으로 구성하고 한 줄에 할당 한 다음 연속적인 라인에 동적 속성을 할당하는 데 의존했습니다. 이것은 저에게 가장 많은 길을 줬습니다. 감사합니다.
Shafiq Jetha

8

스프레드 연산자를 사용하여 이전 객체를 기반으로 새 객체를 만들 수 있습니다

interface MyObject {
    prop1: string;
}

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

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

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

TypeScript는 원본 객체의 모든 필드를 추론하고 VSCode는 자동 완성 등을 수행합니다.


좋지만
prop3

6

가장 간단한 것은 다음과 같습니다

const obj = <any>{};
obj.prop1 = "value";
obj.prop2 = "another value"

5

다음과 같은 방법으로 기존 객체에 멤버를 추가 할 수 있습니다

  1. 유형 확대 (읽기 : 인터페이스 확장 / 전문화)
  2. 원본 객체를 확장 유형으로 캐스트
  3. 개체에 멤버를 추가
interface IEnhancedPromise<T> extends Promise<T> {
    sayHello(): void;
}

const p = Promise.resolve("Peter");

const enhancedPromise = p as IEnhancedPromise<string>;

enhancedPromise.sayHello = () => enhancedPromise.then(value => console.info("Hello " + value));

// eventually prints "Hello Peter"
enhancedPromise.sayHello();

1
나를위한 최고의 솔루션. 오늘 새로운 것을 배웠습니다. 감사합니다
Maurice

이 코드로 TS2352 오류가 발생합니다
ya_dimon

@ya_dimon은 TypeScript Playground에서 시도해보십시오 : typescriptlang.org/play 잘 작동합니다!
Daniel Dietrich

@DanielDietrich는 이제 작동합니다. thx, 무슨 일이 있었는지 전혀 몰라요.
ya_dimon

아니에요! shift);)
Daniel Dietrich

5

이 작업을 수행 할 수 없으므로

obj.prop = 'value';

TS 컴파일러와 린터가 엄격하지 않으면 다음과 같이 작성할 수 있습니다.

obj['prop'] = 'value';

TS 컴파일러 또는 linter가 엄격한 경우 다른 대답은 typecast입니다.

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

3
tsconfig.json에서 'noImplicitAny : false'인 경우
LEMUEL ADANE

그렇지 않으면 GreeneCreations가 답변 할 수 있습니다.
LEMUEL ADANE

4

'any'로 타입 캐스팅하여 모든 종류의 객체에 새로운 속성을 저장하십시오.

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

나중에 확장 객체를 'any'로 다시 캐스팅하여 검색 할 수 있습니다.

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

이것은 완전히 올바른 해결책입니다. 객체를 가지고 있다고하자. o o : ObjectType; .... 나중에 o를 (<any> o)로 캐스트 할 수 있습니다 .newProperty = 'foo'; (<any> o) .newProperty와 같이 검색 할 수 있습니다. 컴파일러 오류가 없으며 매력처럼 작동합니다.
매트 애슐리

이 브레이크는 지능 ...이 방법은 있지만 지능을 유지하는 방법이 있습니까?
pregmatch

4

유형이 Object(즉, 키-값 쌍 ) 임을 보장하려면 다음을 사용하십시오.

const obj: {[x: string]: any} = {}
obj.prop = 'cool beans'

4
  • 사례 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


4

당신은 이것을 사용할 수 있습니다 :

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


3

가장 안전한 방법은 안전한 타이핑을 사용하는 것입니다.

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

3

이전 유형을 유지하려면 객체를

  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;

3

다음은 Object.assign속성 변경 시마다 변수 유형을 자동으로 조정 하는 특수 버전입니다 . 추가 변수, 형식 어설 션, 명시 적 형식 또는 개체 복사본이 필요하지 않습니다.

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 }

참고 : 샘플 은 TS 3.7 어설 션 함수를 사용 합니다 . 의 반환 유형 assign입니다 void달리 Object.assign.


1

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:PropAble = getTheGivenObject();
k.props = "value for props";

1

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' 
};

1
코드를 사용해
보았지만

1
attributes내부 에서 필드 를 초기화하려고 SomeClass 하면 public attributes: IType = {}; pastebin.com/3xnu0TnN
Nerdroid

1

이 시도:

export interface QueryParams {
    page?: number,
    limit?: number,
    name?: string,
    sort?: string,
    direction?: string
}

그런 다음 사용하십시오

const query = {
    name: 'abc'
}
query.page = 1

0

완전히 안전한 형식의 유일한 솔루션은 이것 이지만, 조금 말이 많으며 여러 객체를 만들어야합니다.

당신이 경우 해야한다 먼저 빈 객체를 만든 다음 두 가지 솔루션 중 하나를 선택하십시오. 를 사용할 때마다 as안전이 상실 된다는 점에 유의하십시오 .

보다 안전한 솔루션

의 내부 유형 object안전합니다.getObject 즉, object.a유형은string | undefined

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

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

짧은 해결책

의 유형은 object이다 안전하지 내부 getObject수단, object.a형식이 될 것입니다 string심지어 할당하기 전에.

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

function getObject() {
  const object = {} as Example;
  object.a = 'one';
  object.b = 1;
  return object;
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.