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