Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Properties passed via the constructor do not always get set. #5116

Open
hedgybeats opened this issue Mar 2, 2025 · 0 comments
Open

Properties passed via the constructor do not always get set. #5116

hedgybeats opened this issue Mar 2, 2025 · 0 comments

Comments

@hedgybeats
Copy link

Describe the bug

When instantiating new Typescript classes by passing data to constructor, some properties do not get set if that class extends another class. (Only the properties of the extended class get set when passing data via the constructor).

Version used

V14.2.0

To Reproduce

Server side classes:

public class PaginationFilter: BaseFilter
{
    public int PageNumber { get; set; }

    public int PageSize { get; set; } = int.MaxValue;
}

public class BaseFilter
{
    public string Keyword { get; set; }
}

Code generation settings:

        var codeGenerationSettings = new TypeScriptClientGeneratorSettings
        {
            ClassName = "{controller}Client",
            GenerateClientClasses = true,
            Template = TypeScriptTemplate.Angular,
            RxJsVersion = 7.0M,
            UseSingletonProvider = true,
            IncludeHttpContext = false,
            HttpClass = HttpClass.HttpClient,
            WithCredentials = false,
            InjectionTokenType = InjectionTokenType.InjectionToken,
            BaseUrlTokenName = baseUrlTokenName,
            OperationNameGenerator = new MultipleClientsFromOperationIdOperationNameGenerator(),
            ClientBaseClass = string.Empty,
            QueryNullValue = string.Empty,
            GenerateClientInterfaces = false,
            GenerateOptionalParameters = false,
            ExcludedParameterNames = [],
            ExceptionClass = "ApiException",
            WrapDtoExceptions = false,
            WrapResponses = false,
            UseTransformOptionsMethod = false,
            UseTransformResultMethod = false,
            WrapResponseMethods = [],
            GenerateDtoTypes = true,
            ImportRequiredTypes = true
        };

        codeGenerationSettings.TypeScriptGeneratorSettings.ModuleName = moduleName;
        codeGenerationSettings.TypeScriptGeneratorSettings.Namespace = string.Empty;
        codeGenerationSettings.TypeScriptGeneratorSettings.TypeScriptVersion = 4.3M;
        codeGenerationSettings.TypeScriptGeneratorSettings.InlineNamedDictionaries = false;
        codeGenerationSettings.TypeScriptGeneratorSettings.InlineNamedAny = false;
        codeGenerationSettings.TypeScriptGeneratorSettings.ExportTypes = true;
        codeGenerationSettings.TypeScriptGeneratorSettings.TypeStyle = TypeScriptTypeStyle.Class;
        codeGenerationSettings.TypeScriptGeneratorSettings.EnumStyle = TypeScriptEnumStyle.Enum;
        codeGenerationSettings.TypeScriptGeneratorSettings.UseLeafType = false;
        codeGenerationSettings.TypeScriptGeneratorSettings.NullValue = TypeScriptNullValue.Undefined;
        codeGenerationSettings.TypeScriptGeneratorSettings.DateTimeType = TypeScriptDateTimeType.Date;
        codeGenerationSettings.TypeScriptGeneratorSettings.GenerateDefaultValues = true;
        codeGenerationSettings.TypeScriptGeneratorSettings.MarkOptionalProperties = true;
        codeGenerationSettings.TypeScriptGeneratorSettings.GenerateCloneMethod = false;
        codeGenerationSettings.TypeScriptGeneratorSettings.ExcludedTypeNames = [];
        codeGenerationSettings.TypeScriptGeneratorSettings.HandleReferences = false;
        codeGenerationSettings.TypeScriptGeneratorSettings.GenerateConstructorInterface = true;
        codeGenerationSettings.TypeScriptGeneratorSettings.ConvertConstructorInterfaceData = false;
        codeGenerationSettings.TypeScriptGeneratorSettings.ExtendedClasses = [];
        codeGenerationSettings.TypeScriptGeneratorSettings.TemplateDirectory = null;

Auto-generated output:

export class BaseFilter implements IBaseFilter {
    advancedSearch?: Search | undefined;
    keyword?: string;
    advancedFilter?: Filter | undefined;

    constructor(data?: IBaseFilter) {
        if (data) {
            for (var property in data) {
                if (data.hasOwnProperty(property))
                    (<any>this)[property] = (<any>data)[property];
            }
        }
    }

    init(_data?: any) {
        if (_data) {
            this.advancedSearch = _data["advancedSearch"] ? Search.fromJS(_data["advancedSearch"]) : <any>undefined;
            this.keyword = _data["keyword"];
            this.advancedFilter = _data["advancedFilter"] ? Filter.fromJS(_data["advancedFilter"]) : <any>undefined;
        }
    }

    static fromJS(data: any): BaseFilter {
        data = typeof data === 'object' ? data : {};
        let result = new BaseFilter();
        result.init(data);
        return result;
    }

    toJSON(data?: any) {
        data = typeof data === 'object' ? data : {};
        data["advancedSearch"] = this.advancedSearch ? this.advancedSearch.toJSON() : <any>undefined;
        data["keyword"] = this.keyword;
        data["advancedFilter"] = this.advancedFilter ? this.advancedFilter.toJSON() : <any>undefined;
        return data;
    }
}

export interface IBaseFilter {
    advancedSearch?: Search | undefined;
    keyword?: string;
    advancedFilter?: Filter | undefined;
}

export class PaginationFilter extends BaseFilter implements IPaginationFilter {
    pageNumber?: number;
    pageSize?: number;
    orderBy?: string[];

    constructor(data?: IPaginationFilter) {
        super(data);
    }

    override init(_data?: any) {
        super.init(_data);
        if (_data) {
            this.pageNumber = _data["pageNumber"];
            this.pageSize = _data["pageSize"];
            if (Array.isArray(_data["orderBy"])) {
                this.orderBy = [] as any;
                for (let item of _data["orderBy"])
                    this.orderBy!.push(item);
            }
        }
    }

    static override fromJS(data: any): PaginationFilter {
        data = typeof data === 'object' ? data : {};
        let result = new PaginationFilter();
        result.init(data);
        return result;
    }

    override toJSON(data?: any) {
        data = typeof data === 'object' ? data : {};
        data["pageNumber"] = this.pageNumber;
        data["pageSize"] = this.pageSize;
        if (Array.isArray(this.orderBy)) {
            data["orderBy"] = [];
            for (let item of this.orderBy)
                data["orderBy"].push(item);
        }
        super.toJSON(data);
        return data;
    }
}

export interface IPaginationFilter extends IBaseFilter {
    pageNumber?: number;
    pageSize?: number;
    orderBy?: string[];
}

Typescript usage:

const filter = new ApiClient.PaginationFilter({
    keyword: 'Search String',
    pageSize: 10,
    pageNumber: 1
});

console.assert(filter.pageSize === 10); // filter.pageSize stays undefined
console.assert(filter.pageNumber === 1); // filter.pageNumber stays undefined

Expected behavior

I expect that filter.pageSize and filter.pageNumber get assigned the values that are passed via the constructor.

Additional context

While all the data that is initially passed is forwarded to the baseFilter class constructor:

    constructor(data?: IPaginationFilter) {
        super(data);
    }

The IBaseFilter type ends up hiding the 2 properties that would exist in the IPaginationFilter type:

    constructor(data?: IBaseFilter) {
        if (data) {
            for (var property in data) {
                if (data.hasOwnProperty(property))
                    (<any>this)[property] = (<any>data)[property];
            }
        }
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant