codememo

TypeScript에서 오브젝트에 속성을 동적으로 할당하려면 어떻게 해야 합니까?

tipmemo 2023. 3. 14. 21:40
반응형

TypeScript에서 오브젝트에 속성을 동적으로 할당하려면 어떻게 해야 합니까?

Javascript에서 오브젝트에 속성을 프로그램적으로 할당하려면 다음과 같이 합니다.

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

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

유형 '{}'의 값에 'prop' 속성이 없습니다.

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

인덱스 타입

It is possible to denote 다음을 나타낼 수 있습니다.obj as ~하듯이any, 그러나 그것은 형식적인 목적을 달성한 것입니다.하지만, 그것은 타이프스크립트를 사용하는 전체 목적을 망친다. obj = {} implies 암시하다obj is an 는 입니다.Object. 로 시 .하 marking it as?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;

Record<Keys,Type> 유형

업데이트(2020년 8월):@transang이 댓글로 이 얘기를 꺼냈어요.

Record<Keys,Type>는 타이프 스크립트의 유틸리티 유형입니다.속성 이름을 알 수 없는 키와 값의 쌍에 대해 훨씬 깔끔한 대체 수단입니다.가 있다Record<Keys,Type>입니다.{[k: Keys]: Type}서 ''는Keys ★★★★★★★★★★★★★★★★★」Type.IMO, IMO.

비교를 위해서

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

된다

var obj: Record<string,any> = {}

MyType Record 할 수 .

interface MyType extends Record<string,any> {
    typesafeProp1?: number,
    requiredProp1: string,
}

이것이 원래의 질문에 대한 답변이지만, @GreeneCreations의 답변은 문제에 접근하는 방법에 대한 다른 관점을 제공할 수 있습니다.

또는 올인원:

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

이 솔루션은 개체에 특정 유형이 있을 때 유용합니다.오브젝트를 다른 소스로 가져올 때처럼요.

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

저는 약간...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 = {};

온라인으로 시험해 보다

컴파일러는 필요에 따라 출력할 수 있다고 불평합니다.하지만, 이것은 효과가 있습니다.

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

JavaScript의 "구성"에 대해 생각할 때 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은 평면 객체가 있을 때 가장 잘 작동합니다.nullable 속성을 포함하는 두 개의 중첩된 개체를 결합하는 경우 정의되지 않은 상태로 truthy 값을 덮어쓸 수 있습니다.Object.assign 인수의 순서를 주의하면 문제가 없습니다.

이를 위한 또 하나의 옵션은 컬렉션으로 속성에 액세스하는 것입니다.

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

확산 연산자를 사용하여 이전 개체를 기반으로 새 개체를 생성할 수 있습니다.

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

케이스 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

늦었지만 간단한 대답

let prop = 'name';
let value = 'sampath';
this.obj = {
   ...this.obj,
   [prop]: value
};

가장 심플한 것은 다음과 같습니다.

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

.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 어설션 기능을 사용합니다.반환 유형:assignvoid는, 「」와 달리, 「」는 다릅니다.Object.assign.

이렇게 할 수 없기 때문에:

obj.prop = 'value';

TS 컴파일러와 린터가 엄격하지 않은 경우 다음과 같이 기술할 수 있습니다.

obj['prop'] = 'value';

TS 컴파일러 또는 린터가 엄격한 경우, 또 다른 답은 타이프캐스트입니다.

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

이 「」라고 합니다.Object(즉, 키와 의 쌍), 사용:

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

기존 오브젝트에 멤버를 추가할 수 있습니다.

  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();

안전한 타이핑을 사용하는 것이 가장 좋습니다.권장할 수 있는 방법은 다음과 같습니다.

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

Angular에 대한 @jmvtrinidad 솔루션 확장,

이미 입력된 개체로 작업할 때 새 속성을 추가하는 방법은 다음과 같습니다.

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

" " " 를 사용하고 otherProperty

<div *ngIf="$any(user).otherProperty">
   ...
   ...
</div>

앵귤러 $any()의 캐스팅으로서anyTypeScript와 동일하게 입력합니다.<any>또는as anycast 가 사용됩니다.

새 속성을 'any'로 입력하여 모든 종류의 개체에 저장합니다.

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

나중에 확장 개체를 다시 '임의'로 캐스팅하여 가져올 수 있습니다.

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

이전 유형을 보존하려면 개체를 임시로 임의의 위치에 캐스팅하십시오.

  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에서 개체에 동적으로 속성을 할당합니다.

그러기 위해서는 다음과 같은 타입 스크립트인터페이스를 사용할 필요가 있습니다.

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

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

그렇게 쓸 수 있다

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

완전 타입 세이프한 솔루션은 이것뿐입니다만, 약간 말이 많아 여러 개체를 작성해야 합니다.

먼저 빈 개체를 만들어야 하는 경우 다음 두 가지 솔루션 중 하나를 선택하십시오.사용할 때마다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;
}

할 수 (는 지금 을 타이프스크립트 버전으로 사용하고 .)"typescript": "~4.5.5")

let contextItem = {} as any;

이제 모든 속성을 추가하고 어디서나 사용할 수 있습니다.맘에 들다

contextItem.studentName = "kushal";

나중에 다음과 같이 사용할 수 있습니다.

console.log(contextItem.studentName);

나는 바로 이 주제에 대해 기사를 썼다.

Typescript – 실행 시 개체와 해당 유형을 확장합니다.

https://tech.xriba.io/2022/03/24/typescript-enhance-an-object-and-its-type-at-runtime/

다음과 같은 Typescript 개념에서 영감을 얻을 수 있습니다.

Typescript를 사용하는 경우 type safety를 사용해야 합니다.이 경우 naked Object와 '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 = getTheGivenObject() as PropAble;
k.props = "value for props";

이 선언을 추가하여 경고를 무음화할 수 있습니다.

declare var obj: any;

상태 저장소로 기능하는 개체의 일부를 업데이트하려고 할 때 이 문제가 발생했습니다.

type State = {
  foo: string;
  bar: string;
  baz: string;
};

const newState = { foo: 'abc' };

if (someCondition) {
  newState.bar = 'xyz'
}

setState(newState);

시나리오에서는 「」를 사용하는 솔루션이 됩니다.Partial<T>. 를?토큰. 토큰에 대한 자세한 내용은 유형의 모든 속성을 옵션으로 설정하는 방법에 대한 자세한 SO 항목을 참조하십시오.

가 해결했습니다.Partial<T>:

type State = {
  foo: string;
  bar: string;
  baz: string;
};

const newState: Partial<State> = { foo: 'abc' };

if (someCondition) {
  newState.bar = 'xyz';
}

setState(newState);

이는 프레간테가 답변에서 설명한 것과 유사하지만, 이 특정 사용 사례(프런트 엔드 애플리케이션에서 흔히 볼 수 있는)에 대해 좀 더 명확한 그림을 그리고 싶었습니다.

ES6 사용Map이 고정 수 있는 , 그의 임의의 은 임의의 것으로 합니다.

이게 제가 지향할 가이드라인인 것 같아요.ES6 맵은 "Typescript(타입스크립트)"의 ES6 맵에 기재된 바와 같이 타이프스크립트로 작성할 수 있습니다.

옵션 속성의 주요 사용 사례는 기능의 "옵션" 매개 변수입니다.이름 있는 파라미터 JavaScript 사용(typescript에 기반) 이 경우 허용되는 속성의 정확한 목록을 미리 알 수 있습니다.따라서 가장 현명한 방법은 명시적인 인터페이스를 정의하고 임의로 사용할 수 있는 모든 것을 만드는 것입니다.?https://stackoverflow.com/a/18444150/895245 에서 가능한 한 많은 타입 체크를 받을 수 있습니다.

const assert = require('assert')

interface myfuncOpts {
  myInt: number,
  myString?: string,
}

function myfunc({
  myInt,
  myString,
}: myfuncOpts) {
  return `${myInt} ${myString}`
}

const opts: myfuncOpts = { myInt: 1 }
if (process.argv.length > 2) {
  opts.myString = 'abc'
}

assert.strictEqual(
  myfunc(opts),
  '1 abc'
)

그리고 Map이 정말로 임의적이고(무한히 많은 가능한 키) 고정된 유형인 경우 다음과 같이 Map을 사용합니다.

const assert = require('assert')
const integerNames = new Map<number, string>([[1, 'one']])
integerNames.set(2, 'two')
assert.strictEqual(integerNames.get(1), 'one')
assert.strictEqual(integerNames.get(2), 'two')

테스트 대상:

  "dependencies": {
    "@types/node": "^16.11.13",
    "typescript": "^4.5.4"
  }

이것을 시험해 보세요.

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

그럼 쓰세요

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

언급URL : https://stackoverflow.com/questions/12710905/how-do-i-dynamically-assign-properties-to-an-object-in-typescript

반응형