해결된 질문
작성
·
423
·
수정됨
1
안녕하세요,
질문 :
타입스크립트, 클래스에서 사용하는 변수에 초기값을 빈 객체({})로 정의할 경우,
해당 빈 객체의 타입을 정의할 때, 타입단언, as를 사용하지 않고,
다른 방법으로 정의할 수 있을까요?
다음과 같은 코드가 있습니다.
interface Props{
email:string;
password:string
}
class Store<State>{
// state에 초깃값으로 빈객체{}를 설정할때,
// 빈 객체{}에 대한 타입이슈
public state = {} as State
..중략..
}
export default new Store<Props>({
email:'hello@hello.com',
password:'hello'
})
Store란 클래스에서 state라는 변수를 빈 객체를 값으로 초기값으로 정의하였습니다.
즉, 멤버변수 state는 빈객체{}를 초기값으로 사용할 것이며
멤버변수 state는 인터페이스 Props 형태를 따르도록 규정하고 싶습니다.
public state = {} as State
빈객체{}의 타입을 정의할때,
타입단언 as를 사용하지 않고 다른 방법이 있을까요?
어떤 값을 빈 객체를 초기값으로 시작한다고 코드 작성할때,
as, 타입단어의 유혹?을 받곤 합니다.
{}객체에 대한 타입정의에 대해 검색해보니
Record타입으로 정의하는 내용이 나와 다음과 같은 코드로 변경해보았는데,
public state:Record<State,string> = {}
다음과 같은 에러가 발생했습니다.
reduce 함수를 사용할 때도, 초깃값을 빈객체{}로 사용할 경우에도 as를 사용해,
누산기(acc)의 타입을 as로 단언 한 코드를 종종 보곤 하는데요,
위와 같이 어떤 변수에 빈 객체{}를 초기값으로 혹은 값으로 할당하고 타입을 정의해야 할때,
타입단언을 쓰지 않고, 다른 방법이 있는지 문의 드립니다!
답변 1
0
안녕하세요 프린이님
interface Props {
email:string;
password:string
}
class Test<State> {
public store: State
constructor(initialState: State) {
this.store = initialState;
}
}
new Test<Props>({
email: 'hello',
password: "hello",
})
위와 같이 처리하면 될 것 같은데 굳이 아래와 같이 미리 초기화 하는 특별한 이유가 있을까요?
public store: State = {}
네 의도를 파악했습니다
그런데 제공해주신 코드의 특수성이 있는 것 같네요. 원래 넘어온 state로
this.state = state
하면 타입 에러가 발생하지 않는데 에러가 발생하는 이유는 특수한 목적을 갖고 Object.defineProperty
로 this.state
를 초기화하고 계셔서 에러가 발생하고 있습니다.
이럴 땐 제가 생각했을 땐 as
외엔 특별한 방법이 없을 것 같은데 만약에 제가 지금 작성한 코드를 수정해보라고 한다면 아래와 같이 Proxy
사용해서 수정할 것 같습니다.
interface State {
photo: string;
name: string;
email: string;
blog: string;
github: string;
repository: string;
}
type StoreObservers<S> = {
[K in keyof S]?: Array<(value: S[K]) => void>;
};
class Store<S extends Record<string, any>> {
private state: S;
private observers: StoreObservers<S> = {};
constructor(initialState: S) {
this.state = new Proxy(initialState, {
get: (target, prop: string) => {
return target[prop];
},
set: (target, prop: string, value) => {
this.notify(prop, value);
return true;
}
});
}
private notify(prop: keyof S, value: any) {
if (Array.isArray(this.observers[prop])) {
this.observers[prop]?.forEach(observer => observer(value));
}
}
}
const aboutStore = new Store<State>({
photo: '',
name: '',
email: '',
blog: '',
github: '',
repository: '',
});
안녕하세요, 애프터캠프님! 답변 남겨주셔 감사드립니다.
알려주신 코드로 변경해 사용하겠습니다!
다만 궁금한 사항이 있어 몇가지 추가 문의 남깁니다!
#1. object.defineProperty
로 this.state
를 매번 초기화 하는 코드가 안 좋은 코드인가요?
#2. proxy
를 사용해 기존 코드를 변경하는 이유가 무엇일까요? proxy에 어떤 특징/특성 때문에 proxy로 코드를 변경 하신걸까요?
#1. object.defineProperty로 this.state를 매번 초기화 하는 코드가 안 좋은 코드인가요?
초기에 문의 드린 클래스 Store 코드에서,
매번 object.defineProperty로 this.state를 매번 초기화 하는 것이 안 좋은 코드일까요?
음,, 뭐 그런 객체를 변경가능한/변경하지 못하게 하는 그런 이슈 때문인건지요?
proxy로 코드를 추천해주시면서, 기존 코드가 갖는 문제점이 있는건지 문득 궁금해서 문의 드립니다.
#2. proxy를 사용해 기존 코드를 변경하는 이유가 무엇일까요? proxy에 어떤 특징/특성 때문에 proxy로 코드를 변경하신걸까요?
텍스트 적으로 proxy의 개념을 공부한 적은 있는데, 직접 proxy를 코드에서 사용해본 적이 없어서 문의 드립니다!
아는 내용만 사용하고 익숙하다보니, 새로운 개념(proxy)이 있어도 적용할 수 없어서 (proxy)학습 차원에서 문의 드립니다!
어떤 맥락에서 proxy의 특징과 이유가 있어서 사용해주셨는지 알려주시면,
추천해주신 코드를 뜯어보고 (proxy를) 학습하는데 ,(이후 proxy를 코드에 적용해보는데) 큰 도움이 될 듯합니다!
귀한 시간 내어, 읽어주시고 답글 남겨주셔 감사드립니다!
1,2번 답변을 한꺼번에 드리면,
작성하신 코드 자체는 문제는 없는데, 가독성 측면에서 변경했습니다. 가독성이라는 것도 주관적일 수 있어서 제 논리를 말씀드려보면...
MDN 문서를 보면 Proxy 설명이 아래와 같이 되어있습니다.
The Proxy object enables you to create a proxy for another object, which can intercept and redefine fundamental operations for that object.
기존의 object의 기능을 인터셉트해서 기존의 동작을 재정의한다고 되어있는데 프린이님이 작성하신 코드가 딱 그런 코드라서 Proxy를 사용하면 그 의도가 분명해지지 않나 생각합니다.
안녕하세요!
위의 내용에 관련해, 현재 작업중인 코드로 연결해서 문의 드립니다!
빈객체{}의 타입을 지정하려는 이유가,
해당 빈객체{}에 내용을 다르게 할당하여
종류/목적별로 다양한 객체를 생성할 목적입니다.
다음의 코드가 있습니다.
Store 클래스를 new 호출로 사용해서 Store 클래스에 전달한 인자의 종류대로 state를 만들 수 있습니다.
다음은 클래스 Store를 사용하는 경우 입니다.
코드1.
코드2.
코드1에 해당하는 state 객체를 만들 수 있고,
코드2에 해당하는 state 객체를 만들 수 있습니다.
즉 Store클래스로 다양한 내용물을 담은 state를 만들려 하다보니
우선 Store 클래스의 state를 빈객체{}로 정의하게 됐습니다!
as로 단언을 하면 에러 없이 해결되나,
!할당단언 같은 눈가리고 아웅?하는 문법이 위와 같이 빈객체{} 타입정의에 좋은건지 궁금합니다!
혹시 as 말고 Record유틸리티 타입으로도 위와 같은 상황을 정의 가능할까요?
위의 내용처럼 key:value 형식의 내용말고
함수 타입 같은 경우도 빈객체{}의 타입을 지정해야하는 경우도 있는데,
이것도 어떻게 하면 좋을까요?
질문의 포인트는 빈 객체{}에 대한 타입정의 라서 혹시 좋은 의견 있으시면 조언을 요청드립니다!!
감사합니다!