How can I expect two parameters of a function to be of the same value of a specific Union type

119 Views Asked by At

I am trying to create a function that takes two parameters, first is a union type, second is type that depends on the type of the first parameter.

For example:

type Fruit = "Orange" | "Apple" | "Banana";

function doubleFruit<T extends Fruit, K extends T>(fruit1: T, fruit2: K) {
   // When execution reaches here
   // both fruit1 and fruit2 need to be the same fruit
}

Now, These statements work as expected

 
 // Gives error since Orange is not same as Apple neither banana
 doubleFruit("Orange", "Apple"); 
 doubleFruit("Orange", "Banana");

 // Runs peacefully, since both are same fruit
 doubleFruit("Apple", "Apple");


But when the first parameter is dynamic, something strange happens

function run(x: "Orange" | "Apple") {

 // Should not work, since x could be anything
 doubleFruit(x, "Orange");
}

I assume that since x could be either Orange or Apple, the second parameter being Orange does not follow the criteria of both parameters being same.

Edit: Here's what I want to achieve

type Fruit = "Orange" | "Apple" | "Banana";


function doubleFruit<T extends Fruit, K extends T>(fruit1: T, fruit2: K) {
  // When execution reaches here
  // both fruit1 and fruit2 need to be the same fruit
}

function run(x: "Orange" | "Apple") {
  // I need this to work: 
  //   Whatever be the value of x, the other parameter would be equivalent,
  //   hence should be allowed
  doubleFruit(x, x); 

  // But not these: 
  //   since x could be anything, specifically sending one of 
  //   values shouldn't work
  doubleFruit(x, "Orange")
  doubleFruit(x, "Apple")
  
}

I need a way to satisfy the above behaviour.

1

There are 1 best solutions below

1
On

Please try if that is working for your case:

type Fruit = "Orange" | "Apple" | "Banana";

function doubleFruit<T extends Fruit, K>(fruit1: T, fruit2: K & T) {
   // When execution reaches here
   // both fruit1 and fruit2 need to be the same fruit
}

doubleFruit("Orange", "Apple"); 
doubleFruit("Orange", "Banana");

doubleFruit("Apple", "Apple");

const x: "Orange" | "Apple" = "Apple";

doubleFruit(x, "Orange");