【问题标题】:Type Guard Typescript not inferring function rest parameters correctlyType Guard Typescript 未正确推断函数剩余参数
【发布时间】:2020-10-31 19:06:37
【问题描述】:

我有一个带有类型保护和函数剩余参数的 Typescript 示例:

interface BaseProps {
  username: string;
  password: string;
}

type Props = BaseProps & (
  | {isAdmin: true, adminName: string} 
  | {isAdmin: false}
)


// Doesn't works
const myFn = ({isAdmin, ...rest}: Props) => {
  if(isAdmin === true) {
    rest.adminName; // Property 'adminName' does not exist on type '{ username: string; adminName: string; } | { username: string; }'.
  }
}

// It works
const myFn2 = (args: Props) => {
  if(args.isAdmin === true) {
    args.adminName;
  } 
}

其余参数和类型保护有什么问题?

TS Playground


更新解决方案:

我找到了解决方案,使用Assert Functions 解决了问题。

declare function assertType<T>(val: unknown): asserts val is T;

const myFn = ({password, isAdmin, ...rest}: Props) => {

  if(isAdmin === true) {
    
    assertType<Omit<Props & {isAdmin: true}, keyof Props>>(rest);

    rest.adminName; // <=== HERE

    rest.username;

    // Should be error
    rest.password;
  }
}

TS Playground

【问题讨论】:

    标签: typescript typeguards rest-parameters


    【解决方案1】:

    Props 的类型是

    { 用户名: 字符串, isAdmin: true, adminName: 字符串 } | {用户名:字符串,isAdmin:假}

    当您在 Prop 类型的对象(例如 if 语句)上声明 isAdmin 的值时,typescript 就能够缩小 { username: string, isAdmin: true, adminName: string }{ username: string, isAdmin: false } 之间的实际类型。

    如果通过解构删除isAdminrest的类型就变成了

    { 用户名:字符串,管理员名称:字符串 } | {用户名:字符串}

    isAdminrest 变得不相关,缩小rest 类型的唯一方法是断言adminName 属性的存在。

    也许您不应该在这种特定情况下使用休息参数。您也可以在if 中手动转换rest 变量。

    【讨论】:

      猜你喜欢
      • 2019-02-22
      • 2020-04-09
      • 2018-08-07
      • 1970-01-01
      • 2020-03-03
      • 2018-11-19
      • 2019-01-13
      • 2014-01-31
      • 2019-08-02
      相关资源
      最近更新 更多