RicoSuter / NSwag

The Swagger/OpenAPI toolchain for .NET, ASP.NET Core and TypeScript.
http://NSwag.org
MIT License
6.62k stars 1.23k forks source link

TypeScript override keyword not added everywhere it should (overridden members and clone method) #4794

Open mchlroy opened 4 months ago

mchlroy commented 4 months ago

I see that override keyword support was added in Add support for TypeScript 4.3 override keyword & NJsonSchema upgrade, but it seems that there are other places where it should be there but it is not, making the code no compile if we are using the noImplicitOverride option in tsconfig.

  1. If we are using the GenerateCloneMethod, the clone method does not have the override keyword for child classes.
  2. Child classes with overridden members do not have these members marked with the override keyword

Minimal Reproduction

Downloaded the most recent version of NSwagStudio (NSwag 14.0.3.0, NJsonSchema 11.0.0.0)

Specification

{
  "openapi": "3.0.1",
  "components": {
    "schemas": {
      "Parent": {
        "required": ["$type", "id"],
        "type": "object",
        "properties": {
          "$type": {
            "type": "string"
          },
          "id": {
            "type": "string"
          },
          "propertyToOverride": {
            "type": "boolean",
            "default": true
          }
        },
        "additionalProperties": false
      }
    },
    "Child": {
      "type": "object",
      "allOf": [
        {
          "$ref": "#/components/schemas/Parent"
        }
      ],
      "properties": {
        "propertyToOverride": {
          "type": "boolean",
          "default": true
        }
      },
      "additionalProperties": false
    }
  }
}

Settings for TypeScript Client

Generated Outputs

export class Parent implements IParent {
    $type!: string;
    id!: string;
    propertyToOverride?: boolean;

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

    init(_data?: any) {
        if (_data) {
            this.$type = _data["$type"];
            this.id = _data["id"];
            this.propertyToOverride = _data["propertyToOverride"] !== undefined ? _data["propertyToOverride"] : true;
        }
    }

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

    toJSON(data?: any) {
        data = typeof data === 'object' ? data : {};
        data["$type"] = this.$type;
        data["id"] = this.id;
        data["propertyToOverride"] = this.propertyToOverride;
        return data;
    }

    clone(): Parent {
        const json = this.toJSON();
        let result = new Parent();
        result.init(json);
        return result;
    }
}

export interface IParent {
    $type: string;
    id: string;
    propertyToOverride?: boolean;
}

export class Child extends Parent implements IChild {
    propertyToOverride?: boolean;

    constructor(data?: IChild) {
        super(data);
        if (!data) {
            this.propertyToOverride = true;
        }
    }

    override init(_data?: any) {
        super.init(_data);
        if (_data) {
            this.propertyToOverride = _data["propertyToOverride"] !== undefined ? _data["propertyToOverride"] : true;
        }
    }

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

    override toJSON(data?: any) {
        data = typeof data === 'object' ? data : {};
        data["propertyToOverride"] = this.propertyToOverride;
        super.toJSON(data);
        return data;
    }

    clone(): Child {
        const json = this.toJSON();
        let result = new Child();
        result.init(json);
        return result;
    }
}

export interface IChild extends IParent {
    propertyToOverride?: boolean;
}

As you can see, neither clone() or propertyToOverride in the child class have have the override keyword, cause typescript errors: image

Thank you!