【问题标题】:How to conditionally type a key depending on another key of same object如何根据同一对象的另一个键有条件地键入一个键
【发布时间】:2021-12-24 17:50:25
【问题描述】:

我试图创建一种类型,该类型会根据使用的枚举值而改变:

enum StatusEnum {
  UPDATE = 'update',
  CREATE = 'create'
}

type LogKeyType<K extends StatusEnum> =
  K extends StatusEnum.UPDATE ? Record<string, any> : undefined

type Props = {
  status: StatusEnum
  log: LogKeyType<status> // <-- here is the key that should change type depending on status
  // other keys...
}

对于这一行:log: LogKeyType&lt;status&gt; 我收到一条错误消息,指出状态指的是一个值,但被用作一种类型,我没有设法通过这个错误。

然后我也尝试使用泛型类型:

enum StatusEnum {
  UPDATE = 'update',
  CREATE = 'create'
}

type LogKeyType<K extends StatusEnum> =
  K extends StatusEnum.UPDATE ? Record<string, any> : undefined

type Props<K extends StatusEnum> = {
  status: K
  log: LogKeyType<K> 
  // other keys...
}

但 typescript 无法分辨 log 的类型。

这是在这个用例中使用的:

if (props.status === StatusEnum.UPDATE) {
  // do something with props.log that won't be undefined
}

我也可以直接检查日志是否未定义,但它不会那么花哨。

编辑:

这是我在 Baka 回答的评论中所说的错误:playground link

【问题讨论】:

    标签: typescript types type-inference


    【解决方案1】:

    你要找的是discriminated union

    这是一个如何将它与枚举一起使用的示例:

    import React from 'react';
    
    enum StatusEnum {
      UPDATE = 'update',
      CREATE = 'create'
    }
    
    interface BaseProps {
      status: StatusEnum;
      // other keys...
      someArbitraryKey: string;
    }
    
    interface Update extends BaseProps {
      status: StatusEnum.UPDATE;
      log: Record<string, any>;
    }
    
    interface Create extends BaseProps {
      status: StatusEnum.CREATE;
    }
    
    type Props = Update | Create;
    
    export const Component: React.FC<Props> = props => {
      if (props.status === StatusEnum.UPDATE) {
        return <div>{props.log}</div>; // no type error
      }
    
      if (props.someArbitraryKey.length) { // someArbitraryKey is always available
        return <div>{props.log}</div>; // error, undefined log
      }
    
      return <div />;
    }
    

    TS Playground

    【讨论】:

    • 好答案,如果您还直接在答案中添加注释代码,那就太好了(当然保留到 TS Playground 的链接)。
    • 非常感谢,虽然我有一个错误,无法在 TS 操场上重现,但链接太长,无法发表评论,我将编辑我的问题。
    • @HartWoom &gt; Property 'log' does not exist on type 'Create' — 您确定要比较 props.status 与您这边的正确枚举值吗?此外,如果您在 IDE/编辑器中发现此错误并且 if 条件中的枚举值正确,请检查 tsc 输出,可能只是 IDE 或 LSP 插件相关问题
    • @Baka 是的,我确定 if 条件。错误也在我的控制台中,tsc 不会让我编译。但这不是一个真正的问题,我只需要在 if 括号中声明一个 const 即可。
    猜你喜欢
    • 2023-03-14
    • 1970-01-01
    • 2017-08-03
    • 2023-01-16
    • 2022-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-11
    相关资源
    最近更新 更多