简单动态密钥名称的类型

ogsagwnx  于 2022-10-15  发布在  React
关注(0)|答案(1)|浏览(147)

我希望能够为动态密钥生成类型(这将是类型编号)。我有两种非常相似的类型:

type UseCalculatePayments = () => {
  totalPayments: number;
  aggregate: number;
  condition: boolean;
};
type UseCalculateCommissions = () => {
  totalCommissions: number;
  aggregate: number;
  condition: boolean;
};

唯一的区别是第一个密钥名(totalPaymentstotalCommissions)。所以我想为他们两个都创建一个类型:

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;
};

但现在条件的类型错误为Property 'condition' of type 'boolean' is not assignable to 'string' index type 'number',因为它假定所有密钥都是一个数字。
所以我的问题是:如何纠正动态的[key: string]: number类型?我也尝试使用Record类型,但失败了。
要为您提供更好的背景信息,请参阅:
Stackblitz演示:https://stackblitz.com/edit/react-starter-typescript-h3ckn4?file=App.tsx
代码:

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 };
};

另外,这里是界面好还是类型好?谢谢你在这里帮我的忙。

4dc9hkyq

4dc9hkyq1#

您可以使用Map类型和模板文字类型来创建具有所需键的对象。
然后将其与所需的其他属性组合在一起。

type TotalKey<Str extends string> = {
  [Prop in keyof "total" as `total${Str}`]: number;
};

type UseCalculate<T extends string> = () => {
    aggregate: number;
    condition: boolean;
} & TotalKey<T>;

type UseCalculateCommissions = UseCalculate<"Commissions">;
type UseCalculatePayments = UseCalculate<"Payments">;

const foo: UseCalculateCommissions = () => ({
    aggregate: 5,
    condition: true,
    totalCommissions: 5,
})

const bar: UseCalculatePayments = () => ({
    aggregate: 5,
    condition: true,
    totalPayments: 5,
})

相关问题