부모 클래스의 유형을 추론하기 위해 기본 클래스를 가져 오는 데 문제가 있습니다.
abstract class Record {
//...
static findRecord(id: number){
// this creates will create an instance of the prototype "this"
// prototype of "this" will equal Node later
return new (Object.getPrototypeOf(this))(id)
}
}
class Node extends Record {
statements(): Array<Statement> {
// ...
}
}
let node = Node.findRecord(1)
// type is "any" (as findRecord doesn't infer the type as "Node", because Object.getPrototypeOf(this)) can equal anything)
node.statements() // This has no typings in vscode
레코드의 유형이 레코드를 인스턴스화하는 클래스 (이 경우 Node)라는 것을 typescript로 알고 싶습니다.
에 대한 타이핑 node
을 사용할 수 Node
있도록 인스턴스화 된 유형이 필요하며 .statements()
코드 복제를 피하고 .NET 에서 확장되는 각 클래스에 넣어야합니다 Record
.
여기 @Titian의 대답에 따라 특정 클래스 인스턴스를 설명 findRecord
하는 일반 함수로 메서드 를 만들어야합니다 T
. this
인수를 무시 된 첫 번째 인수로 사용하면 typescript가 호출 할 때 T
의 값을 기반으로 형식을 유추 할 수 있습니다 this
.
abstract class MyRecord {
constructor(id: number) {
}
static findRecord<T>(this: new (id: number) => T, id: number): T {
return new this(id);
}
}
개인적으로 나는 "상속이 나쁘다"라는 만트라를 구입했기 때문에 공유 static
논리를 각 레코드 유형에 대해 생성자에 인수로 전달하여 각 레코드 유형에 대해 인스턴스화 할 수있는 별도의 클래스로 이동할 것 입니다.
class RecordFinder<T extends BaseRecord> {
private readonly recordClass: RecordConstructor<T>;
constructor( recordClass: RecordConstructor<T> ) {
this.recordClass = recordClass;
}
find(id: number): T {
return new this.recordClass(id);
}
}
interface BaseRecord {
id: number;
}
type RecordConstructor<T extends BaseRecord> = new (id: number) => T;
여기 recordClass
에서는 인터페이스 를 기반으로 유형을 제한하고 있으므로 MyNode
확장 여부는 중요 MyRecord
하지 않습니다.
const nodeFinder = new RecordFinder(MyNode);
const node = nodeFinder.find(1);
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다