我如何实现类型缩小,即使缩小逻辑被提取到其他地方?

huangapple go评论67阅读模式
英文:

How can I accomplish type narrowing even if the narrowing logic is extracted elsewhere?

问题

I'm trying to conditionally render a react component TransactionSummary which requires paymentSetup to be defined.

Edit: paymentSetup is a value of type PaymentSetupType | null which is required by TransactionSummary.

I've extracted the conditional logic as follows to keep the code clean.

const canShowTransactionSummary = Boolean(paymentSetup && several_other_conditions);

return (
   canShowTransactionSummary && 
   <TransactionSummary paymentSetup={paymentSetup} ...non_relevant_props />
)

It is possible for paymentSetup to be null, and I've excluded this possibility by calculating canShowTransactionSummary. However, I still see a TS warning -

type 'PaymentSetupType | null' is not assignable to type 'PaymentSetupType'.
  Type 'null' is not assignable to type 'PaymentSetupType'.

I can resolve this by either

a. including the conditions directly before TransactionSummary ...
(which I want to avoid in order to keep the code clean) or
b. by using
a type annotation (not a preferred option either)

Is there another way to accomplish this?

Edit: Simplified code for TransactionSummary is below. Only paymentSetup is a relevant prop for our discussion.

type PaymentSetupType {
  unitCost: number;
  // other properties (not important)
}

interface Props {
  currency: string;
  quantity: number;
  paymentSetup: PaymentSetupType;
}

const TransactionSummary = ({
  currency,
  quantity,
  paymentSetup,
}: Props): ReactElement => {
  const { i18n } = useTranslation();

  return (
    <div>
      Donating 
        {getFormatedCurrency(
          i18n.language,
          currency,
          paymentSetup.unitCost * quantity
        )} for {quantity} trees
    </div>
  );
};
英文:

I'm trying to conditionally render a react component TransactionSummary which requires paymentSetup to be defined.

Edit: paymentSetup is a value of type PaymentSetupType | null which is required by TransactionSummary.

I've extracted the conditional logic as follows to keep the code clean.

const canShowTransactionSummary = Boolean(paymentSetup &amp;&amp; several_other_conditions);

return (
   canShowTransactionSummary &amp;&amp; 
   &lt;TransactionSummary paymentSetup={paymentSetup} ...non_relevant_props /&gt;
)

It is possible for paymentSetup to be null and I've excluded this possibility by calculating canShowTransactionSummary. However, I still see a TS warning -

type &#39;PaymentSetupType | null&#39; is not assignable to type &#39;PaymentSetupType&#39;.
  Type &#39;null&#39; is not assignable to type &#39;PaymentSetupType&#39;.

I can resolve this by either

a. including the conditions directly before TransactionSummary ...
(which I want to avoid in order to keep the code clean) or
b. by using
a type annotation (not a preferred option either)

Is there another way to accomplish this?

Edit: Simplified code for TransactionSummary is below. Only paymentSetup is a relevant prop for our discussion.

type PaymentSetupType {
  unitCost: number;
  // other properties (not important)
}

interface Props {
  currency: string;
  quantity: number;
  paymentSetup: PaymentSetupType;
}

const TransactionSummary = ({
  currency,
  quantity,
  paymentSetup,
}: Props): ReactElement =&gt; {
  const { i18n } = useTranslation();

  return (
    &lt;div&gt;
      Donating 
        {getFormatedCurrency(
          i18n.language,
          currency,
          paymentSetup.unitCost * quantity
        )} for {quantity} trees
    &lt;/div&gt;
  );
};

答案1

得分: 1

以下是翻译好的部分:

"Instead of constructing a Boolean, an explicit null check will successfully narrow the type:

type PaymentSetupType = {};

const paymentSetup = Math.random() < .5 ? {} : null;
const canShowTransactionSummary = paymentSetup != null;

if (canShowTransactionSummary) {
  fn(paymentSetup); // no error
}

function fn(paymentSetup: PaymentSetupType) {}"

"TypeScript jsut doesn't seem to deal well with making inferences based on the result of that Boolean constructor. Even just a standard truthy check would successfully narrow the type:

if (paymentSetup) {
  fn(paymentSetup); // no error
}

On a side note, you mention you're trying to keep the code clean, but neither casting potential null values to Boolean, nor using short-circuit boolean operators to control program flow are the hallmarks of clean code."

英文:

Instead of constructing a Boolean, an explicit null check will successfully narrow the type:

type PaymentSetupType = {};

const paymentSetup = Math.random() &lt; .5 ? {} : null;
const canShowTransactionSummary = paymentSetup != null;

if (canShowTransactionSummary) {
  fn(paymentSetup); // no error
}

function fn(paymentSetup: PaymentSetupType) {}

TypeScript jsut doesn't seem to deal well with making inferences based on the result of that Boolean constructor. Even just a standard truthy check would successfully narrow the type:

if (paymentSetup) {
  fn(paymentSetup); // no error
}

On a side note, you mention you're trying to keep the code clean, but neither casting potential null values to Boolean, nor using short-circuit boolean operators to control program flow are the hallmarks of clean code.

huangapple
  • 本文由 发表于 2023年5月17日 14:30:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/76269118.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定