typescript 一个组件阻止了通常的存在性检查或None,但如何避免这种重复?

bsxbgnwa  于 2023-01-18  发布在  TypeScript
关注(0)|答案(1)|浏览(108)

在我的组件/页面中,我需要多次使用此模式:

{#if player.name}
  {player.name}
{:else}
  None
{/if}

因此我创建了一个名为MaybeNone的新组件:

<script lang="ts">
    export let condition = false;
</script>

{#if !condition}
    None
{:else}
    <slot />
{/if}

像这样使用:

<MaybeNone condition={!!player.name}>
  Name is: {player.name}
</MaybeNone>

但有时候我需要用一些方法

{#if player.name}
  {calculate_player_name(player)}
{:else}
  None
{/if}

与:

export const calculate_player_name = (
    player: Pick<Player, 'name' | 'nickname'>
): string => {
    // calculate result...

    return result;
};

player?: {
    name?: string | null;
    nickname?: string | null;
    team?: string | null;
    id: string;
    createdAt: Date;
  } | null;
}>;

现在MaybeNone组件的用法不好:

<MaybeNone condition={!!player.name}>
  <!-- There is an error here because I need to check player.name before calling `calculate_player_name()` obviously -->
  {calculate_player_name(player)}
</MaybeNone>

所以我不得不用

<MaybeNone condition={!!player.name}>
  {#if player.name}
    {calculate_player_name(player)}
  {/if}
</MaybeNone>

因为打字错误当然是:

Type 'undefined' is not assignable to type 'Pick<Player, "name" | "nickname">'.ts(2345)

这使得MaybeNone的使用没有用或者没有我想象的那么好。
你能建议一个替代方案吗?一个解决方案?
感谢您的帮助!

wa7juj8i

wa7juj8i1#

将通过具有插槽属性的通用组件来实现这一点,如下所示:

<script lang="ts">
  type T = $$Generic;
  export let maybe: T | null | undefined;

  // Workaround for type not being narrowed correctly in parent
  $: notNull = maybe as T; 
</script>

{#if maybe}
  <slot value={notNull} />
{:else}
  None
{/if}

然后可以沿着以下方式使用:

<MaybeNone maybe={player} let:value>
  {calculate_player_name(value)}
</MaybeNone>

这应该根据函数的类型来工作,但是如果你需要检查name是否也被定义了,那么它们可能是不准确的,确保是这样的话可能会有点冗长:

<MaybeNone maybe={player?.name == null ? null : player} let:value>
  {calculate_player_name(value)}
</MaybeNone>

(If player本身可以是undefined/null,在属性访问上确实应该有一个?.,否则TS严格的空值检查会导致错误。)

相关问题