I want to define a type, which has a property "path" and other properties which only can occur together. The following objects should be legal:
{ path: 'abc' }
{ path: 'def', valueTemplate: {}, valuePath: '' }
{ path: 'ghi', valueTemplate: {}, $valuePath: '' }
The following objects should not be legal, as a "valueTemplate" may only occur with a "($)valuePath":
{ path: 'abc', valueTemplate: {} }
{ path: 'def', valuePath: '' }
{ path: 'ghi', $valuePath: '' }
I thought this should express my conditions as type:
type DynamicInputTarget = { path: string } & (
{ valueTemplate?: never; valuePath?: never; $valuePath?: never }
| { valueTemplate: object; valuePath: string }
| { valueTemplate: object; $valuePath: string }
)
At first it seems to work:
const t1: DynamicInputTarget = { path: 'abc' } // works fine
const t2: DynamicInputTarget = { path: 'abc', valuePath: '' } // fails, as expected
const t3: DynamicInputTarget = { path: 'abc', valuePath: '', valueTemplate: {} } // works fine
But when I try to handle t3, I get an unexpected compile time error:
const hasDollarValuePath = !!t3.$valuePath // unexspected error on accessing $valuePath
Error text:
Property '$valuePath' does not exist on type '{ path: string; } & { valueTemplate: object; valuePath: string; }'. Did you mean 'valuePath'?
Why is that and how can I do this right??
CodePudding user response:
You need to make the other prop also never
in your possible values:
export type DynamicInputTarget = { path: string }
& (
{ valueTemplate?: never; valuePath?: never; $valuePath?: never }
| { valueTemplate: object; valuePath: string; $valuePath?: never } // here
| { valueTemplate: object; $valuePath: string; valuePath?: never } // and here
);