Home > Software design >  Make sure properties always occur together in type definition
Make sure properties always occur together in type definition

Time:09-23

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??

Link to TS-Playground

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
  );

Playground

  • Related