I want to be able to generate types for a dynamic key (that will be of type number). I have two very similar types:
type UseCalculatePayments = () => {
totalPayments: number;
aggregate: number;
condition: boolean;
};
type UseCalculateCommissions = () => {
totalCommissions: number;
aggregate: number;
condition: boolean;
};
The only difference is the first key-name (totalPayments vs totalCommissions). So I wanted to create a type for them both:
type UseDynamicTransactions = (type: string) => {
[key: string]: number; // I want this type key to dynamically be called `total${type}`, so it would accept, for example, totalPayments, totalCommissions or totalSales, all of type number
aggregate: number;
condition: boolean;
};
But now the condition has a type error of Property 'condition' of type 'boolean' is not assignable to 'string' index type 'number' as it presumably expects all the keys to be a number.
So my question is: how can the dynamic [key: string]: number type be corrected? I tried to use a Record type too, but this failed.
To give you some better context, see:
The stackblitz demo: https://stackblitz.com/edit/react-starter-typescript-h3ckn4?file=App.tsx
The code:
export const App = () => {
// const { totalPayments, aggregate, condition } = useCalculatePayments();
const { totalPayments, aggregate, condition } =
useDynamicTransactions('Payments');
const {
totalCommissions,
aggregate: aggregateCommissions,
condition: commissionCondition,
// } = useCalculateCommissions();
} = useDynamicTransactions('Commissions');
const {
totalSales,
aggregate: aggregateSales,
condition: saleCondition,
} = useDynamicTransactions('Sales');
return (
<Fragment>
<div>
<h2>Payments</h2>
<p>Aggregate: {aggregate}</p>
<p>Total: {totalPayments}</p>
<p>Condition: {condition.toString()}</p>
</div>
<div>
<h2>Commissions</h2>
<p>Aggregate: {aggregateCommissions}</p>
<p>Total: {totalCommissions}</p>
<p>Condition: {commissionCondition.toString()}</p>
</div>
<div>
<h2>Sales</h2>
<p>Aggregate: {aggregateSales}</p>
<p>Total: {totalSales}</p>
<p>Condition: {saleCondition.toString()}</p>
</div>
</Fragment>
);
};
type UseDynamicTransactions = (type: string) => {
[key: string]: number; // I want this type key to dynamically be called `total${type}`, so it would accept, for example, totalPayments, totalCommissions or totalSales, all of type number
aggregate: number;
condition: boolean;
};
const useDynamicTransactions: UseDynamicTransactions = (type) => {
// does some calcs etc...
return { [`total${type}`]: 6, aggregate: 40, condition: false };
};
type UseCalculatePayments = () => {
totalPayments: number;
aggregate: number;
condition: boolean;
};
type UseCalculateCommissions = () => {
totalCommissions: number;
aggregate: number;
condition: boolean;
};
const useCalculatePayments = () => {
return { totalPayments: 5, aggregate: 100, condition: false };
};
const useCalculateCommissions = () => {
return { totalCommissions: 3, aggregate: 20, condition: false };
};
Also, is an interface or a type better here? Thanks for any help here.