Is it possible to do discriminated unions in TypeScript over two properties instead of one? Here is a TypeScript playground:
type BrowserRemote = {
remote: true
foo: string
}
type BrowserLocal = {
bar: string
}
type NodeRemote = {
remote: true
baz: string
}
type NodeClientLocal = {
client: true
bing: string
}
type NodeClientRemote = {
boom: string
}
type NodeType = NodeRemote | NodeClientLocal | NodeClientRemote
type BrowserType = BrowserRemote | BrowserLocal
function convertNode(input: NodeType) {
console.log(input)
}
function convertBrowser(input: BrowserType) {
console.log(input)
}
convertNode({
remote: true,
baz: 'foo'
})
convertNode({
remote: true,
boom: 'foo'
})
Basically, I have two functions convertNode and convertBrowser, one for Node.js and one for the browser. The Node.js function can take 3 input styles depending on if it's making a remote request (connecting to a REST API internally), or making a local request (remote is undefined). The local request can be either coming from a client or not coming from a client (client is undefined). The browser can be either remote or not remote, so it's a simpler version than Node.js. So let's focus on Node.js.
The "discriminated union" property really is a combination of 2 properties:
remote: true, client: undefined | falseremote: undefined | false, client: trueremote: undefined | false, client: undefined | false
But I would like to not have to pass in client: undefined or remote: undefined into my function calls. Likewise, I would like the API to stay like this, with 2 properties instead of 1 property. 1 property might look like this:
source: 'remote'source: 'local:client'source: 'local'
I may go with that approach if absolutely necessary, but I wanted to see if this was possible somehow to do discriminated unions on the 2 properties, to get that TypeScript playground to work. Is it possible? If not, why not? If so, how could you get it to work?
Note: Each permutation will have some shared properties and some unique properties. So remote/local:client/local will each have some similar properties, and some different properties. In addition, they might have a property named the same thing, but a different type, like this:
type NodeLocalClient = {
client: true
file: ArrayBuffer
}
type NodeLocal = {
file: string
}
Granted, I could really try to have the props of different types have different names, but it may not always be desirable to try and enforce that.