bcherny / json-schema-to-typescript

Compile JSON Schema to TypeScript type declarations
https://bcherny.github.io/json-schema-to-typescript-browser/
MIT License
2.93k stars 392 forks source link

Feature request: Support OpenAPI's "discriminator" directive #239

Open vanslly opened 5 years ago

vanslly commented 5 years ago

In AOS 3 there's provision for oneOf being used along with a discriminator, which allows specifying an array where the types are discriminated based on a property. https://swagger.io/docs/specification/data-models/oneof-anyof-allof-not/

{
    "definitions": {
        "Ledger": {
            "required": [
                "transactions"
            ],
            "type": "object",
            "properties": {
                "transactions": {
                    "uniqueItems": false,
                    "type": "array",
                    "items": {
                        "oneOf": [
                            {
                                "$ref": "#/definitions/JournalingTransaction"
                            },
                            {
                                "$ref": "#/definitions/SalesReturnTransaction"
                            }
                        ],
                        "discriminator": "transactionType"
                    }
                }
            }
        },
        "TransactionType": {
            "enum": [
                "JournalingTransaction",
                "SalesReturnTransaction"
            ],
            "type": "string",
            "tsEnumNames": [
                "JournalingTransaction",
                "SalesReturnTransaction"
            ]
        },
        "AccountEntry": {
            "amount": {
                "format": "double",
                "type": "number"
            }
        },
        "Transaction": {
            "required": [
                "transactionType",
                "accountEntries"
            ],
            "type": "object",
            "properties": {
                "transactionType": {
                    "$ref": "#/definitions/TransactionType"
                },
                "accountEntries": {
                    "uniqueItems": false,
                    "type": "array",
                    "items": {
                        "$ref": "#/definitions/AccountEntry"
                    }
                }
            }
        },
        "JournalingTransaction": {
            "allOf": [
                {
                    "$ref": "#/definitions/Transaction"
                },
                {
                    "required": [
                        "reason"
                    ],
                    "type": "object",
                    "properties": {
                        "reason": {
                            "type": "string"
                        }
                    }
                }
            ]
        },
        "SalesReturnTransaction": {
            "allOf": [
                {
                    "$ref": "#/definitions/Transaction"
                },
                {
                    "required": [
                        "returnItemId"
                    ],
                    "type": "object",
                    "properties": {
                        "returnItemId": {
                            "type": "string"
                        }
                    }
                }
            ]
        }
    }
}

Expected TypeScript:

export interface Ledger {
    transactions: (
        | JournalingTransaction
        | SalesReturnTransaction)[];
}

export const enum TransactionType {
    JournalingTransaction = 'JournalingTransaction',
    SalesReturnTransaction = 'SalesReturnTransaction'
}

export interface AccountEntry {
    amount: number;
}

export interface Transaction {
    accountEntries: AccountEntry[];
}

export type JournalingTransaction = Transaction & {
    transactionType: TransactionType.JournalingTransaction;
    reason: string;
};

export type SalesReturnTransaction = Transaction & {
    transactionType: TransactionType.SalesReturnTransaction;
    returnItemId: string;
};
bcherny commented 3 years ago

Will leave this open for now, in case there's interest from others in this feature.

cjol commented 3 years ago

Is that a valid schema for the discriminator? I don't see any way of linking SalesReturnTransaction to TransactionType.SalesReturnTransaction other than them having the same name which seems flaky.