简体   繁体   中英

enforce property order in a typescript interface

I am building a typescript interface to an API that I do not control. The API is xml based and expects properties in a particular order. These properties are not all required, but if they exist they must come in their proper order. Example:

在此处输入图像描述

database and query are required, the others are not but if they exist rowOffset must come before rowCount and rowCount before formatValues

// Valid request
<database>my data</database>
<query>select * from some_table</query>
<formatValues>true</formatValues>

// Valid request
<database>my data</database>
<query>select * from some_table</query>
<rowOffset>1</rowOffset>
<formatValues>true</formatValues>

// Invalid request
<database>my data</database>
<query>select * from some_table</query>
<formatValues>true</formatValues>
<rowOffset>1</rowOffset> // formatValues must come after rowOffset if it exists

The typescript signature for this request looks like this

sqlQuery(database: string, query: string, options: object) : Promise

database and query are required and must be specified, the other options go to an object and we extend it with our required params and convert the whole thing to xml and send it on its way. The problem is that the options will be converted to xml attributes in order and so I need to enforce the order of the attributes, without enforcing the existence of these attributes.

I thought a map could do the trick, but I can't figure out how to make a custom type from a map. I could do an interface

interface OptionalParams {
    rowOffset? : string,
    rowCount? : string,
    formatValues? :string,
}

but this won't enforce the order they exist in relative to each other. Is there any such type that can do this?

I found this question while searching for the same thing. I don't know if you're still having trouble with this, but I learned about Map in ES6 thanks to this: https://www.jstips.co/en/javascript/map-to-the-rescue-adding-order-to-object-properties/

Full doc: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map

Since this question has had some renewed interest, I will post the solution I ended up with. For every API method, I keep a map of the appropriate params. In my case this is made easier by the fact that every service requires the params in the same order relative to each other. That is, row offset will always come before row count for any API method that accepts them. The map ends up looking like this

this.paramMap = new Map([['addRecord', ['table', 'returnModifiedData',]],
                         ['deleteRecord', ['table', 'keyValue',]],
                         ['getColumnInfoList', ['database', 'table',]], ... );

This map is then used to reorder the parameters before the request is sent like so

// Add params to the request in the propper order
addParams(params: XmlmcParams, paramMap: Array<string>): void {
    let orderedParams: XmlmcParams = {};
    // ensure that all the params are in the proper order
    paramMap.forEach((v) => {
        if (params.hasOwnProperty(v)) {
            orderedParams[v] = params[v];
        }
    });
    // add ordered params to request
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM