4

I have some code for a form:

interface FormProps {
  regexPreset?: RegexPresets;
  customRegex?: RegExp;
  description?: string;
  inputTitle: string;
  errorMessage?: string;
}
const Form: React.FC<FormProps> = props => {
  return <div> somestuff </div>
} 

If I pass in a customRegex, I want the compiler to throw an error if errorMessage is not passed (make errorMessage a mandatory property).

The closest thing that I've come to is this StackOverflow post, but I'm unsure whether I can apply this to my use case.

Any pointers would be gladly received.

Jamie
  • 3,105
  • 1
  • 25
  • 35

2 Answers2

1

I think it's feasible to utilize what's mentioned in that post you mentioned in your post, but before going into advanced typings I'd like to evaluate if the simplest solution possible is sufficient. So–if you were to include a customRegex, you would be forced to also include a errorMessage–then this type should cover your use-case:

interface FormProps {
  regexPreset?: RegexPresets;
  description?: string;
  inputTitle: string;
  customRegexProps?: {
    customRegex: RegExp;
    errorMessage: string;
  }
}
gqstav
  • 1,984
  • 1
  • 12
  • 18
  • So I did think about this approach, however, the `errorMessage` is needed as an individual prop because I want to be able to pass an `errorMessage` without a customRegex. – Jamie Mar 29 '20 at 15:18
  • I see. Maybe you find this solution: https://www.typescriptlang.org/play/#code/FASwdgLgpgTgZgQwMZQAQDED2MC2AFGTABwGdUBvYVVGKAcygA8CoSoIB+ALlQCV6mLNhBIBuKqgAmrJDBBEIITGG6oSEOWDrjq4IgFcIAFRAQANlB7rN2ibEIwAsqxIIGq6+FsBfYKEiwiCgY2PiEpADqpgAWAML66pg4-AyMqEzQYJJkWLgExCSU1EgJEEkpTDwpAKKMRDrpMA7OJK4MVhpe4r7ASMrqqEasELk4PKP5pKgAPiF54SRREHGl5QJpALwUEsWryes8YFAA7nz0tUQAFAD0AHQAVNcAlMA9QA more suitable for your form? Essentially defining the custom RegExp form and the default one as separate entities. – gqstav Mar 29 '20 at 18:17
1

To simplify lets say we have following props

interface FormProps {
  inputTitle: string;
  description?: string;
  
  customRegex?: string;
  errorMessage: string;
}

Here 'inputTitle' prop is mandatory, description is optional but errorMessage prop has to be there (mandatory) only when customRegex (optional) prop is present.

Create a type for non-conditional props

interface FormMainProps {
  description?: string;
  inputTitle: string;
}

Now create a type for conditional props only when conditional prop 'customRegex' is present

interface FormErrorProps {
  customRegex: string; 
  errorMessage: string;
}

Now create an additional type when conditional prop is not present (to give idea for possible values present in object)

interface FormErrorRefProps {
  customRegex?: undefined; 
  errorMessage?: never; 
  // important step; so if customRegex prop is not present errorMessage should not be there and vice-versa
}
 

Now your FormProps will be

type FormProps =  FormMainProps & (FormErrorProps | FormNotErrorProps);

Following scenarios will give error as needed:

let a: FormProps;

a = {
  inputTitle: "Title",
  customRegex: "asdasd"
};

/*
Type '{ inputTitle: string; customRegex: string; }' is not assignable to type 'FormProps'.
Type '{ inputTitle: string; customRegex: string; }' is not assignable to type 'FormMainProps & FormErrorProps'.
    Property 'errorMessage' is missing in type '{ inputTitle: string; customRegex: string; }' but required in type 'FormErrorProps'.ts(2322)
*/


a = {
  inputTitle: "Title",
  errorMessage: "asdasd"
};

/*
Type '{ inputTitle: string; errorMessage: string; }' is not assignable to type 'FormProps'.
Type '{ inputTitle: string; errorMessage: string; }' is not assignable to type 'FormMainProps & FormNotErrorProps'.
    Property 'customRegex' is missing in type '{ inputTitle: string; errorMessage: string; }' but required in type 'FormNotErrorProps'.
*/

while below ones are fine:

a = {
  inputTitle: "Title",
  errorMessage: "asdasd",
  customRegex: "Title",
};

a = {
  inputTitle: "Title"
};
paraS elixiR
  • 1,866
  • 1
  • 18
  • 26