한 속성의 유형이 다른 값에 의해 암시될 수 있는 방식으로 클래스 또는 해당 속성을 입력할 수 있습니까?
유형 testWithTyping
을 사용하는 방법에서 알 수 있듯이 MyType
.
최종 목표는 속성 x
이 속성 이면 가치 가 있음 true
을 클래스에 알릴 수 y
있는 것입니다.
예제 코드:
type MyType = { isSet: false, id: null } | { isSet: true, id: number };
class MyClass {
isSet: boolean = false;
id: number | null = null;
constructor(id?: number) {
if (typeof id === 'number' && id > 0) {
this.isSet = true;
this.id = id;
}
}
test() {
if (this.isSet) {
this.logId(this.id); // TS2345:
// Argument of type 'number | null' is not
// assignable to parameter of type 'number'.
}
}
testWithTyping(this: this & MyType) {
if (this.isSet) {
this.logId(this.id); // Works!
}
}
logId(id: number) {
console.log(id);
}
}
TypeScript에서 클래스와 인터페이스는 현재 공용체 유형을 구현하도록 선언할 수 없습니다. 그것은되었습니다 제안 ,하지만 아무것도 아직 발생하지 않았다. 따라서 컴파일러가 그것이 MyClass extends MyType
사실임 을 이해하는 쉬운 방법은 없습니다 .
이 문제를 처리하기 위해 내가 생각할 수 있는 두 가지 방법은 코드를 리팩토링하는 것과 관련이 있습니다. 의 인스턴스가있는 경우 MyClass
입니다 가능성이 앞뒤로 두 유형 간의 전환 MyType
(첫번째 그것의, 예를 들어 {isSet: false, id: null}
, 다음 나중에이다 {isSet: true, id: 123}
, 그럼 내가 만드는 권하고 싶습니다) MyClass
이MyType
대신 할 을 MyType
. 이것은 상속에 대한 일종의 합성 입니다. 내가 하는 방법은 다음과 같습니다.
class MyClass {
myType: MyType = { isSet: false, id: null };
constructor(id?: number) {
if (typeof id === 'number' && id > 0) {
this.myType = { isSet: true, id };
}
}
test() {
if (this.myType.isSet) {
this.logId(this.myType.id);
}
}
logId(id: number) {
console.log(id);
}
}
주에 대한 모든 참조 것을 this.isSet
또는 this.id
교환되었다 this.myType.isSet
와 this.myType.id
.
그리고 당신은 그것을 테스트할 수 있습니다:
const s = new MyClass(123);
s.test(); // 123
const u = new MyClass();
u.test(); // nothing
다른 방법은 그 그것을 만족에게 당신의 독창적 인 생각을 할 거라고 MyClass
인스턴스가 실제로 있는 MyType
의, 그러나 개인 경우에만 작동 MyClass
인스턴스는 항상 하나 또는의 다른 구성원이 될 것입니다 MyType
노동 조합 및 변경하지 마십시오. 이 경우 다음 MyClass
과 같이 두 개의 관련된 클래스의 합집합을 얻을 수 있습니다.
abstract class MyClassBase {
abstract isSet: boolean;
abstract id: number | null;
abstract test(): void;
logId(id: number) {
console.log(id);
}
}
class MyClassSet extends MyClassBase implements Extract<MyType, { isSet: true }>{
readonly isSet = true;
readonly id: number;
constructor(id: number) {
super();
this.id = id;
}
test() {
this.logId(this.id);
}
}
class MyClassUnset extends MyClassBase implements Extract<MyType, { isSet: false }> {
readonly isSet = false;
readonly id = null;
constructor() {
super();
}
test() { }
}
type MyClass = MyClassSet | MyClassUnset;
const MyClass = class {
constructor(id?: number) {
return (typeof id === 'number' && id > 0) ?
new MyClassSet(id) : new MyClassUnset();
}
} as new (id?: number) => MyClass;
따라서 MyClassSet
및 둘 다 , 모든 공통 기능을 넣을 추상 클래스의 MyClassUnset
하위 클래스입니다 MyClassBase
. this: MyType
거기에 메소드 매개변수 를 지정해야 한다면 그렇게 하는 것이 좋습니다. 그러나 설정 여부에 따라 다른 기능은 해당 하위 클래스에서 구현해야 하므로 그렇게 해서는 안 됩니다.
그런 다음 MyClass
유형은 MyClassSet
및 의 합집합이며 를 반환하는 생성자를 MyClassUnset
만들 수도 있습니다 .MyClass
MyClass
테스트는 이전과 동일하게 작동합니다.
const s = new MyClass(123);
s.test(); // 123
const u = new MyClass();
u.test(); // nothing
나는 일반적으로 구현을 시도하는 대신 MyClass
유형의 속성을 보유하는 첫 번째 솔루션을 선호합니다 . 왜냐하면 그것이 더 간단하기 때문입니다. 그러나 때로는 클래스 계층도 유용합니다.MyType
MyType
알겠습니다. 도움이 되기를 바랍니다. 행운을 빕니다!
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다