4

I use react with typescript.

I want to require only one parameter be accepted from prop3 | prop4. I use a union type like this:

interface General {
  prop1?: boolean
  prop2?: boolean
}

interface Option1 extends General {
  prop3: boolean
}

interface Option2 extends General {
  prop4: boolean
}

type Option1orOtion2 = Option1 | Option2

If I get prop3 I don't want that prop4 will be accepted.

When I do that I get errors about those values. What I do worng?

export default function({
  prop1 = true,
  prop2 = true,
  prop3 = true, // error: Property 'prop3' does not exist on type 'Option1orOtion2'
  prop4 = true  // error: Property 'prop4' does not exist on type 'Option1orOtion2'
}: Option1orOtion2) {
  return <></>
}

EDIT: When I do that with variable there aren't errors, but let me to pass prop3 and also prop4, and I want to get a error about it (Option1 or Option2 ).

var data: Option1orOtion2 = {prop3: false, prop4: false}

Any suggestion?

Thanks in advance!

ESI
  • 1,657
  • 8
  • 18
  • 2
    try -> type Option1orOtion2 = Option1 & Option2 – Manish Singh Apr 20 '20 at 20:04
  • Thank you for your response! I've tried it already and the error was gone, but it doesn't stop me from sending both `prop3` and `prop4` as I expect. Any idea? – ESI Apr 20 '20 at 20:54
  • I took it from [here](https://stackoverflow.com/a/37688375/13029900). – ESI Apr 20 '20 at 20:59
  • I'm also having this issue. Here's a playground example: https://typescript-play.js.org/?jsx=1#code/JYOwLgpgTgZghgYwgAgEJwM4QApQPYAOGyA3gFDLIx54BcyGYUoA5gNxkC+ZZoksiFLkIYAgsggAPSCAAmxdFmFFSFZACM4Ueo2Yh2XHn2jwkyZRlQTpEOQsw58K8pU0AvHU1YduZMAE8CISdiAF5zEPEAHwiRVA4yBDwQRmQAWX8AYTwAWwJk2zBkcIAKEioaABoNODdqzShkTnoLAEpigD5VSigIMABXKBBkACIAC2ARnwSklKLeuWhi5BL20K6XZF6BoeQAHgzsvILwCrxQkeo8EZq3C-cbgHoOrg4gA – wilsonpage Apr 29 '20 at 13:34

1 Answers1

0

This type of problem can be solved using function prototypes, which is used to make overload in ts.

For your case, I have 2 solutions

interface General {
    prop1?: boolean
    prop2?: boolean
}
  
interface Option1 extends General {
    prop3: boolean
}
  
interface Option2 extends General {
    prop4: boolean
}

Using function prototypes to limit the type of parameter that can be given. (I assume the return type to be string, just change it to what you want)

export default function test(param: Option1): string;
export default function test(param: Option2): string;

First solution: using union

export default function test({
    prop1 = true,
    prop2 = true
}: Option1 | Option2): string {
    return ''
}

For this solution, I haven't found any solution to create default for prop3 and prop4.

Second Solution

interface Param extends General {
    prop3?: boolean;
    prop4?: boolean;
}
export default function test({
    prop1 = true,
    prop2 = true,
    prop3 = true,
    prop4 = true
}: Param): string {
    return ''
}

I make another interface which has the prop3 and prop4 set to optional attributes.

Because of the function prototypes, if I call it like below, it will cause error

test({prop4: true, prop3: true}) // error