Home > Mobile >  Different multiple union type in ts
Different multiple union type in ts

Time:04-03

I have 2 types like

interface RowOne {
    id: number;
    value: number;
    median: number;
    timestamp: string;
}

interface RowTwo {
    supply: number;
    pool1: string;
    pool2: string;
    fee: number;
}

Now I declare one Union Type like

interface Total {
   rows: RowOne[] | RowTwo[];
}

As usual, we should have one share field to check that the return type is RowOne or RowTwo

But now I have one function like const data = getTotal(): Total, this function will return data follow RowOne or RowTwo

But when I get data like data.rows[0].supply it says that

Property 'supply' does not exist on type 'RowOne | RowTwo'.

So for this case, How can I pass this error? Thanks

CodePudding user response:

This issue is caused since typescript is unable to find supply common property in the type Row1 | Row2. This happens bacuase the Row1 doesn't have the supply property.

To fix this issue, you have to add checks to determine whether the object contains the specific properties or not. Or better add a function to check the type of the object (Ref: https://stackoverflow.com/a/14426274/5309486 ).

Both approaches are as follow:

const row = data.rows[0];

// Approach 1
function isRowTwo(obj: RowOne | RowTwo): obj is RowTwo {
  return 'supply' in obj && 'pool1' in obj;
}

if (isRowTwo(row)) {
  console.log(row.supply);
}

// Approach 2
if (`supply` in row) {
  console.log(row.supply);
}

You can find the same code at: Playground Link

CodePudding user response:

you can use generic types like this

Playground

interface RowOne {
  id: number;
  value: number;
  median: number;
  timestamp: string;
}

interface RowTwo {
  supply: number;
  pool1: string;
  pool2: string;
  fee: number;
}

interface Total <T>{
  rows:T[]
}

const getTotal = (): Total<RowTwo> => {
  return {
    rows: [{
      supply: 5
      , pool1: ""
      , pool2: ""
      , fee: 2
    }]
  }
}

const data: Total<RowTwo> = getTotal()
data.rows[0]?.supply

CodePudding user response:

In your case, a union type does not work because it only can recognize common attributes between 2 types. You can check the document here

I'd suggest you use a generic type to determine the type's attributes

interface RowOne {
    id: number;
    value: number;
    median: number;
    timestamp: string;
}

interface RowTwo {
    supply: number;
    pool1: string;
    pool2: string;
    fee: number;
}

type Total<T> =  {
   rows: T[];
}

//define data with a specific generic type
const data: Total<RowOne> = {
  rows: [{ id: 1, value: 1, median: 1, timestamp: "1" }]
}

//assign generic types with an union
const getData = (): Total<RowOne | RowTwo> => {
   return data
}

const updatedData = getData()

console.log(updatedData)

Playground

CodePudding user response:

Thanks for strong support from community As I posted before

As usual, we should have one share field to check that the return type is RowOne or RowTwo

So I support we have a solution to make our code better

interface RowOne {
    id: number;
    value: number;
    median: number;
    timestamp: string;
}

interface RowTwo {
    supply: number;
    pool1: string;
    pool2: string;
    fee: number;
}

interface Total <T>{
   rows: T[];
}

In function

const getTotal = async <T>(): Promise<T>

Call:

const data = await getTotal();

Thanks @Nick Vu

  • Related