Voivatko Typescript-interfacet ilmaista ominaisuuksien samanaikaisuusrajoituksia
Onko olemassa vakiokaavaa monoliittisen TypeScriptin rajapinnan tai tyyppimääritelmien sisällä, jolla voitaisiin varmistaa, että ominaisuudet joko ilmestyvät yhdessä tai eivät esiinny lainkaan?
Esimerkiksi kohde voisi olla kelvollinen, jos se näyttäisi tältä...
{
id:"ljklkj",
spellcheck:true,
spellcheckModel:"byzantine",
}
...tai tämä...
{
id:"ljklkj",
}
Kuitenkin se olisi virheellinen, jos jokin tarkistusominaisuuksista esiintyisi erillään.
{
id:"ljklkj",
spellcheckModel:"byzantine",
}
{
id:"ljklkj",
spellcheck:true,
}
Monoliittinen
Tietenkin yllä esitetty yksinkertainen tapaus voitaisiin ratkaista luomalla Data- ja SpellcheckData-tyyppi tai -rajapinta. Sovellukseni tapauksessa kuitenkin esiintyy enemmän kuin yksi samanaikaisesti esiintyvien ominaisuuksien 'klusteri'. Uuden tyypin määrittäminen jokaiselle samanaikaisuuden yhdistelmälle johtaisi tyyppien räjähdysmäiseen kasvuun tämän tapauksen ilmaisemiseksi.
Tästä syystä olen kutsunut ratkaisua 'monoliittiseksi' käyttöliittymäksi. Tietenkin voi olla tarpeen käyttää jonkinlaista koostetta sen määrittelemiseksi.
Mitä olen kokeillut
Olen yrittänyt löytää tämänkaltaisia esimerkkejä Typescriptin kieliviitteestä, mutta ilman tietoa siitä, mitä ominaisuutta tämä voisi olla kutsuttu, (tai ylipäänsä jos se on ominaisuus, joka voidaan ilmaista), minulla on vaikeuksia. Ominaisuudet voivat olla yksittäisesti valinnaisia, mutta en näe tapaa ilmaista samanaikaisuutta.
Liittyvät teknologiat
XML-datan validointiin vastaava ominaisuus käsitellään täällä... https://www.w3.org/wiki/Co-occurrence_constraints
JSONia varten ymmärrän, että skeemakielet kuten Schematron ja Json Content Rules pystyvät ilmaisemaan sivuvaatimuksia.
Työstetty esimerkki
Jos minun pitäisi kuvitella TypeScript-syntaksi co-constraint-tapaukselle, joka on sovellettuna HTTP-parametrisarjoihin Solr-hakukoneessa, se saattaisi näyttää tältä, mikä osoittaa, että voisit valita täyttäväsi Spell- tai Group-parametrit täysin tai et lainkaan - unioni, jossa jokainen tyyppi on valinnainen (merkitty ?) ...
type SolrPassthru =
SolrCoreParams & (
SolrSpellParams? |
SolrGroupParams?
)
Tämä on ristiriidassa alla olevan esimerkin kanssa, joka mielestäni on oikea Typescript, mutta vaatii KAIKKI parametriryhmiin kuuluvat parametrit.
type SolrCoreParams = {
defType: SolrDefType,
boost: SolrBoostType,
}
type SolrSpellParams = {
spellcheck: "true" | "false",
"spellcheck.collate": "true" | "false",
"spellcheck.maxCollationTries": 1,
}
type SolrGroupParams = {
group: "true" | "false",
"group.limit": '4'
"group.sort": 'group_level asc,score desc,published desc,text_sort asc'
"group.main": 'true'
"group.field": 'group_uri'
}
type SolrPassthru =
SolrCoreParams &
SolrSpellParams &
SolrGroupParams
Vastaus #1
Yritä seuraavaa. Näyttää siltä, että se näyttää virheitä oikeissa paikoissa.
type None<T> = {[K in keyof T]?: never}
type EitherOrBoth<T1, T2> = T1 & None<T2> | T2 & None<T1> | T1 & T2
interface Data {
id: string;
}
interface SpellCheckData {
spellcheck: boolean,
spellcheckModel: string,
}
// Two interfaces
var z1: EitherOrBoth<Data, SpellCheckData> = { id: "" };
var z2: EitherOrBoth<Data, SpellCheckData> = { spellcheck: true, spellcheckModel: 'm'};
var z3ERROR: EitherOrBoth<Data, SpellCheckData> = { spellcheck: true};
var z4: EitherOrBoth<Data, SpellCheckData> = { id: "", spellcheck: true, spellcheckModel: 'm'};
interface MoreData {
p1: string,
p2: string,
p3: string,
}
type Monolith = EitherOrBoth<Data, EitherOrBoth<SpellCheckData, MoreData>>
var x1: Monolith = { id: "" };
var x2: Monolith = { spellcheck: true, spellcheckModel: 'm'};
var x3ERROR: Monolith = { spellcheck: true};
var x4: Monolith = { id: "", spellcheck: true, spellcheckModel: 'm'};
var x5ERROR: Monolith = { p1: ""};
var x6ERROR: Monolith = { p1: "", p2: ""};
var x7: Monolith = { p1: "", p2: "", p3: ""};
var x8: Monolith = { id: "", p1: "", p2: "", p3: ""};
var x9ERROR: Monolith = { id: "", spellcheck: true, p1: "", p2: "", p3: ""};
var x10: Monolith = { id: "", spellcheck: true, spellcheckModel: 'm', p1: "", p2: "", p3: ""};
Leikkipuiston linkki
Päivitys
Jos haluat välittää tyypit tuplena, voit käyttää seuraavaa apuvälinettä:
type CombinationOf<T> = T extends [infer U1, infer U2] ? EitherOrBoth<U1, U2> :
T extends [infer U1, infer U2, infer U3] ? EitherOrBoth<U1, EitherOrBoth<U2, U3>> :
T extends [infer U1, infer U2, infer U3, infer U4] ? EitherOrBoth<U1, EitherOrBoth<U2, EitherOrBoth<U3, U4>>> :
never;
type Monolith = CombinationOf<[Data, SpellCheckData, MoreData]>
Jos jotkin ominaisuudet ovat pakollisia:
type Monolith = Data & CombinationOf<[Data, SpellCheckData, MoreData]>
