Ett Typescript-gränssnitt som tillåter en av två valfria nycklar eller ingen, men inte båda
Finns det ett sätt att definiera ett Typescript interface som tillåter ett av 2 valfria nycklar i ett objekt eller ingen av dem, men inte båda?
Här är ett förenklat exempel på vad jag försöker uppnå:
const example1 = { foo: 'some string' }; //should pass - can have only "foo: string"
const example2 = { bar: 42 }; // should pass - can have only "bar: number"
const example3 = {}; // should pass - both foo and bar are optional
const example4 = { foo: 'some string', bar: 42 }; // should throw a Typescript error - can't have both foo and bar simultaneously;
PS. lösningen bör vara ett interface och inte ett type eftersom det i mitt användningsfall extends ett annat interface
Svar #1
type är isomorfisk med interface och du kan kombinera dessa två konstruktioner. Nedan är implementering med typunion och snitt, även lagt till exempel på interface för att visa att det fungerar bra, & är ekvivalent med extends. Tänk på:
interface OtherInterface {
field?: string
}
type Example = ({
foo: string
bar?: never
} | {
foo?: never
bar: number
} | {
[K in any]: never
}) & OtherInterface
const example1: Example = { foo: 'some string' }; // ok
const example2: Example = { bar: 42 }; // ok
const example3: Example = {}; // ok
const example4: Example = { foo: 'some string', bar: 42 }; // error
Lösningen är långrandig, men passar ditt behov. Några förklaringar:
- `
bar?: never` används för att blockera möjligheten att ha ett värde som har ett sådant fält & OtherInterfacehar exakt samma resultat somextends OtherInterface{[K in any]: never}- representerar ett tomt objekt{}
Lekplatslänk
