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

Type collision when extending a parent type or when the same variables are used. #1429

Open
2 of 4 tasks
TrevorDMartin opened this issue May 16, 2023 · 3 comments
Open
2 of 4 tasks

Comments

@TrevorDMartin
Copy link

TrevorDMartin commented May 16, 2023

Sorting

  • I'm submitting a ...

    • bug report
    • feature request
    • support request
  • I confirm that I

    • used the search to make sure that a similar issue hasn't already been submit

Expected Behavior

All types are generated separate from each other. No field collision

Current Behavior

Types are colliding and adding fields to other types or overriding types with the same variable name

Types written like:

type Threshold = "HIGH" | "MEDIUM" | "LOW";
type Base = Record<
    string,
    {
        count: number;
        threshold?: Threshold;
    }
>;

interface PoInfo extends Base {
    type1: {
        count: number;
        threshold?: Threshold;
    };
}
interface Yard extends Base {
    cubes: {
        count: number;
        threshold?: Threshold;
    };
}

interface ParentType {
    yard: Yard;
    poInfo: PoInfo;
}

results in a schema like:

"schemas": {
    "Threshold": {
        "type": "string",
	"enum": [
	    "HIGH",
	    "MEDIUM",
	    "LOW"
	]
    },
    "Yard": {
        "properties": {
	    "cubes": {
	        "properties": {
		    "threshold": {
		        "$ref": "#/components/schemas/Threshold"
		    },
	            "count": {
	                "type": "number",
		        "format": "double"
		    }
		},
		"required": [
			"count"
		],
		"type": "object"
	},

    "PoInfo": {
        "properties": {
	    "cubes": {
	        "properties": {
		    "threshold": {
		        "$ref": "#/components/schemas/Threshold"
		    },
	            "count": {
	                "type": "number",
		        "format": "double"
		    }
		},
		"required": [
			"count"
		],
		"type": "object"
	    },
	    "type1": {
	        "properties": {
		    "threshold": {
		        "$ref": "#/components/schemas/Threshold"
		    },
	            "count": {
	                "type": "number",
		        "format": "double"
		    }
		},
		"required": [
			"count"
		],
		"type": "object"
	    },       
        }
}

ALSO

If two different endpoints define the same variable for a type only one type is represented in the schema.

Steps to Reproduce

I made a repository with similar settings as the one I'm working in to reproduce the bug.

  1. git clone https://github.com/TrevorDMartin/tsoa-type-vs-interface/tree/main
  2. Follow steps in README.md to start application
  3. Go to http://localhost:8080/doc or see generated/swagger.json
  4. Types returned from /complex-schema have additional fields attached
  5. Types returned from '/collision-schema' have been overwritten by '/complex-schema`

Controller is located at src/schema-test/SchemaTestController.ts

There are three seperate files, one for each endpoint, where the data and types are defined.

  • src/schema-test/CollisionTypes.ts
  • src/schema-test/ComplexTypes.ts
  • src/schema-test/SimpleTypes.ts

Context (Environment)

Version of NodeJS: 18.15.0
Version of Typescript: ^5.0.4

  • Confirm you were using yarn not npm: [x]

Current Workaround

Changing the parent type in src/schema-test/ComplexTypes.ts from an interface to a type results in no more extra fields:

interface ComplexSchemaType {
    yard: Yard;
    poAge: PoAge;
    poInfo: PoInfo;
}

// TO 

type ComplexSchemaType = {
    yard: Yard;
    poAge: PoAge;
    poInfo: PoInfo;
}
@github-actions
Copy link

Hello there TrevorDMartin 👋

Thank you for opening your very first issue in this project.

We will try to get back to you as soon as we can.👀

@github-actions
Copy link

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days

@RayJSeth-kr
Copy link

RayJSeth-kr commented Aug 9, 2023

If two different endpoints define the same variable for a type only one type is represented in the schema.

I know this was the secondary issue described here, but this is the issue giving me the runaround today.
Hypothetical example that follows the structure of what I'm trying to accomplish:

Upon further reading of the initial issue, the whole description is actually what I'm experiencing so I'll truncate my initial restating of the problem.

My thoughts on some potential solutions:

  • just roll a simple iterator when collision happens CollidingType_{n} for all collisions
    • feels like conceptually the wrong solution, more like a workaround that might result in bad side-effects
  • hash/obfuscate the resolved module path and prefix type with it
    • more closely aligns tsoa to how TS handles this sort of same name resolution
    • however, pretty complex approach

Ultimately I think if I had been presented with a warning or error that the collision occurred, just that would have been acceptable. Changing the variable name for the type was trivial, but it was trying to find out where the erasure of the second type was coming from that took time.
Any chance of a config option to opt into a 'strict no collisions' mode?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants