일반 클래스의 형식 매개 변수에서 새 개체 만들기
일반 클래스에 형식 매개 변수의 새 개체를 만들려고 합니다. 반에서는 ★★★★★★★★★★★★★★★★★★.View, 이 오브젝트 리스트를 작성하려고 2개입니다new TGridView() 과 같이 표시됩니다
'TGridView' 기호를 찾을 수 없습니다.
코드는 다음과 같습니다.
module AppFW {
// Represents a view
export class View<TFormView extends FormView, TGridView extends GridView> {
// The list of forms
public Forms: { [idForm: string]: TFormView; } = {};
// The list of grids
public Grids: { [idForm: string]: TGridView; } = {};
public AddForm(formElement: HTMLFormElement, dataModel: any, submitFunction?: (e: SubmitFormViewEvent) => boolean): FormView {
var newForm: TFormView = new TFormView(formElement, dataModel, submitFunction);
this.Forms[formElement.id] = newForm;
return newForm;
}
public AddGrid(element: HTMLDivElement, gridOptions: any): GridView {
var newGrid: TGridView = new TGridView(element, gridOptions);
this.Grids[element.id] = newGrid;
return newGrid;
}
}
}
범용 유형으로 개체를 만들 수 있습니까?
범용 코드 내에 새 개체를 만들려면 생성자 함수로 유형을 참조해야 합니다.이 글을 쓰는 대신:
function activatorNotWorking<T extends IActivatable>(type: T): T {
return new T(); // compile error could not find symbol T
}
다음 사항을 기입해야 합니다.
function activator<T extends IActivatable>(type: { new(): T ;} ): T {
return new type();
}
var classA: ClassA = activator(ClassA);
다음 질문을 참조하십시오.클래스 인수를 사용한 범용 유형 추론
에는 모든 있기 에 JavaScript를 사용할 수 T새로운 오브젝트를 만듭니다.
유형을 생성자에 전달하여 일반적이지 않은 방법으로 이 작업을 수행할 수 있습니다.
class TestOne {
hi() {
alert('Hi');
}
}
class TestTwo {
constructor(private testType) {
}
getNew() {
return new this.testType();
}
}
var test = new TestTwo(TestOne);
var example = test.getNew();
example.hi();
제네릭을 사용하여 이 예를 확장하여 유형을 강화할 수 있습니다.
class TestBase {
hi() {
alert('Hi from base');
}
}
class TestSub extends TestBase {
hi() {
alert('Hi from sub');
}
}
class TestTwo<T extends TestBase> {
constructor(private testType: new () => T) {
}
getNew() : T {
return new this.testType();
}
}
//var test = new TestTwo<TestBase>(TestBase);
var test = new TestTwo<TestSub>(TestSub);
var example = test.getNew();
example.hi();
JavaScript측에서는 모든 타입의 정보가 지워지기 때문에 @Sohnee상태와 같이 T를 새로 만들 수는 없지만 type 파라미터가 컨스트럭터에 전달되는 것을 선호합니다.
class A {
}
class B<T> {
Prop: T;
constructor(TCreator: { new (): T; }) {
this.Prop = new TCreator();
}
}
var test = new B<A>(A);
늦은 감이 있지만 @TadasPa의 답변은 조금 조정할 수 있습니다.
TCreator: new() => T
대신
TCreator: { new (): T; }
따라서 결과는 다음과 같아야 합니다.
class A {
}
class B<T> {
Prop: T;
constructor(TCreator: new() => T) {
this.Prop = new TCreator();
}
}
var test = new B<A>(A);
export abstract class formBase<T> extends baseClass {
protected item = {} as T;
}
개체는 어떤 매개 변수도 수신할 수 있지만 Type T는 형식 설명 참조일 뿐 생성자를 통해 생성할 수 없습니다.즉, 클래스 오브젝트는 생성되지 않습니다.
기본 클래스 내에서 일반을 인스턴스화하려고 했습니다.위의 예들은 공장법을 부르기 위해 콘크리트 타입이 필요했기 때문에 나에게 효과가 없었다.
이것에 대해 한동안 조사해 본 결과, 온라인으로 해결책을 찾을 수 없었던 것을 알 수 있었습니다.
protected activeRow: T = {} as T;
내용:
activeRow: T = {} <-- activeRow now equals a new object...
...
as T; <-- As the type I specified.
다 같이
export abstract class GridRowEditDialogBase<T extends DataRow> extends DialogBase{
protected activeRow: T = {} as T;
}
즉, 실제 인스턴스가 필요한 경우 다음을 사용해야 합니다.
export function getInstance<T extends Object>(type: (new (...args: any[]) => T), ...args: any[]): T {
return new type(...args);
}
export class Foo {
bar() {
console.log("Hello World")
}
}
getInstance(Foo).bar();
인수가 있으면 를 사용할 수 있습니다.
export class Foo2 {
constructor(public arg1: string, public arg2: number) {
}
bar() {
console.log(this.arg1);
console.log(this.arg2);
}
}
getInstance(Foo, "Hello World", 2).bar();
다음은 유형 정보를 유지하기 위한 작업입니다.
class Helper {
public static createRaw<T>(TCreator: { new (): T; }, data: any): T
{
return Object.assign(new TCreator(), data);
}
public static create<T>(TCreator: { new (): T; }, data: T): T
{
return this.createRaw(TCreator, data);
}
}
...
it('create helper', () => {
class A {
public data: string;
}
class B {
public data: string;
public getData(): string {
return this.data;
}
}
var str = "foobar";
var a1 = Helper.create<A>(A, {data: str});
expect(a1 instanceof A).toBeTruthy();
expect(a1.data).toBe(str);
var a2 = Helper.create(A, {data: str});
expect(a2 instanceof A).toBeTruthy();
expect(a2.data).toBe(str);
var b1 = Helper.createRaw(B, {data: str});
expect(b1 instanceof B).toBeTruthy();
expect(b1.data).toBe(str);
expect(b1.getData()).toBe(str);
});
저는 이 문제를 직접적으로 해결한다고 생각하여 추가하는 것이 아니라 요청으로 추가하는 것입니다.솔루션에는 SQL 데이터베이스의 테이블을 표시하기 위한 테이블 컴포넌트가 포함됩니다.
export class TableComponent<T> {
public Data: T[] = [];
public constructor(
protected type: new (value: Partial<T>) => T
) { }
protected insertRow(value: Partial<T>): void {
let row: T = new this.type(value);
this.Data.push(row);
}
}
이를 사용하려면 데이터베이스 VW_MyData에 뷰(또는 테이블)가 있으며 쿼리에서 반환되는 모든 엔트리에 대해 VW_MyData 클래스의 컨스트럭터를 히트시켜야 합니다.
export class MyDataComponent extends TableComponent<VW_MyData> {
public constructor(protected service: DataService) {
super(VW_MyData);
this.query();
}
protected query(): void {
this.service.post(...).subscribe((json: VW_MyData[]) => {
for (let item of json) {
this.insertRow(item);
}
}
}
}
반환된 값을 단순히 데이터에 할당하는 것보다 이것이 바람직한 이유는 VW_MyData의 일부 열에 변환을 적용하는 코드가 생성자에 있기 때문입니다.
export class VW_MyData {
public RawColumn: string;
public TransformedColumn: string;
public constructor(init?: Partial<VW_MyData>) {
Object.assign(this, init);
this.TransformedColumn = this.transform(this.RawColumn);
}
protected transform(input: string): string {
return `Transformation of ${input}!`;
}
}
이를 통해 TypeScript로 들어오는 모든 데이터에 대해 변환, 검증 및 기타 작업을 수행할 수 있습니다.그게 누군가에게 통찰력을 주길 바라.
질문에 대한 답변은 아니지만, 이러한 문제에 대한 좋은 라이브러리가 있습니다.https://github.com/typestack/class-transformer (실행시에는 실제로 존재하지 않기 때문에 범용 타입에서는 동작하지 않지만, 모든 작업은 클래스 이름(클래스 컨스트럭터)으로 이루어집니다.)
예:
import {Type, plainToClass, deserialize} from "class-transformer";
export class Foo
{
@Type(Bar)
public nestedClass: Bar;
public someVar: string;
public someMethod(): string
{
return this.nestedClass.someVar + this.someVar;
}
}
export class Bar
{
public someVar: string;
}
const json = '{"someVar": "a", "nestedClass": {"someVar": "B"}}';
const optionA = plainToClass(Foo, JSON.parse(json));
const optionB = deserialize(Foo, json);
optionA.someMethod(); // works
optionB.someMethod(); // works
나는 파티에 늦었지만, 이렇게 일을 처리했다.어레이의 경우 몇 가지 요령이 필요합니다.
public clone<T>(sourceObj: T): T {
var cloneObj: T = {} as T;
for (var key in sourceObj) {
if (sourceObj[key] instanceof Array) {
if (sourceObj[key]) {
// create an empty value first
let str: string = '{"' + key + '" : ""}';
Object.assign(cloneObj, JSON.parse(str))
// update with the real value
cloneObj[key] = sourceObj[key];
} else {
Object.assign(cloneObj, [])
}
} else if (typeof sourceObj[key] === "object") {
cloneObj[key] = this.clone(sourceObj[key]);
} else {
if (cloneObj.hasOwnProperty(key)) {
cloneObj[key] = sourceObj[key];
} else { // insert the property
// need create a JSON to use the 'key' as its value
let str: string = '{"' + key + '" : "' + sourceObj[key] + '"}';
// insert the new field
Object.assign(cloneObj, JSON.parse(str))
}
}
}
return cloneObj;
}
다음과 같이 사용합니다.
let newObj: SomeClass = clone<SomeClass>(someClassObj);
개선은 가능하지만 내 필요에 맞게 작동한다!
나는 이것을 사용한다:let instance = <T>{};통상은, EDIT 1:
export class EntityCollection<T extends { id: number }>{
mutable: EditableEntity<T>[] = [];
immutable: T[] = [];
edit(index: number) {
this.mutable[index].entity = Object.assign(<T>{}, this.immutable[index]);
}
}
다음은 컨스트럭터에 파라미터가 필요한 경우의 예입니다.
class Sample {
public innerField: string;
constructor(data: Partial<Sample>) {
this.innerField = data.innerField;
}
}
export class GenericWithParams<TType> {
public innerItem: TType;
constructor(data: Partial<GenericWithParams<TType>>, private typePrototype: new (i: Partial<TType>) => TType) {
this.innerItem = this.factoryMethodOnModel(data.innerItem);
}
private factoryMethodOnModel = (item: Partial<TType>): TType => {
return new this.typePrototype(item);
};
}
const instance = new GenericWithParams<Sample>({ innerItem : { innerField: 'test' }}, Sample);
언급URL : https://stackoverflow.com/questions/17382143/create-a-new-object-from-type-parameter-in-generic-class
'programing' 카테고리의 다른 글
| 리액트 훅마운트 해제된 구성 요소에서 반응 상태 업데이트를 수행할 수 없음 (0) | 2023.04.04 |
|---|---|
| spring-boot 어플리케이션에서 swag-ui를 기동할 수 없습니다. (0) | 2023.04.04 |
| 어떻게 반응 js에서 한 페이지에서 다른 페이지로 이동합니까? (0) | 2023.04.04 |
| 페이지로 Visual Composer 단축 코드 렌더링 (0) | 2023.04.04 |
| 각도 포함 JSDocJS (0) | 2023.04.04 |