【问题标题】:TypeScript property lookup using filter function使用过滤器功能查找 TypeScript 属性
【发布时间】:2019-07-08 03:57:59
【问题描述】:

我需要使用过滤器函数找到一个键数组以传递给我的 UI 组件。但是 TS warn 总是会引发类型错误。

我试过了

['is_in_building', 'has_outside_access'].filter((v: keyof Unit) => Boolean(unit[v]));

但还是不行。

is_in_buildinghas_outside_access 确实存在于 Unit 类型中。而且filter函数的第一个参数v不能是别的东西。

type.ts

type Unit = {
  is_in_building: boolean,
  has_outside_access: boolean,
  other_keys: boolean,
}

App.tsx

<Checkbox.Group
    value={['is_in_building', 'has_outside_access'].filter(
        v => Boolean(unit[v]) //ts error
    )}
>
    <Checkbox value="is_in_building">In Building</Checkbox>
    <Checkbox value="has_outside_access">Outside Access</Checkbox>
</Checkbox.Group>

错误:(303, 20) TS7053:元素隐式具有“任何”类型,因为“字符串”类型的表达式不能用于索引类型“增强单元”。 在“EnhancedUnit”类型上找不到带有“字符串”类型参数的索引签名。

typescript playground

谁能给我一些建议?

【问题讨论】:

  • 什么是增强单元?
  • 这是单位。我简化了一些代码

标签: reactjs typescript antd


【解决方案1】:

Typescript 推断数组的类型为string[]v 的类型为字符串。 Unit 类型没有字符串类型的索引签名,因此使用字符串进行索引访问被认为是不安全的。

为了安全起见,您可以明确指定数组仅包含 Unit 的键。像这样,

type Unit = {
  is_in_building: boolean,
  has_outside_access: boolean,
  other_keys: boolean,
}

const array: (keyof Unit)[] = ['is_in_building', 'has_outside_access']

<Checkbox.Group value={array.filter(v => Boolean(unit[v]))}

TypeScript Playground

【讨论】:

    【解决方案2】:

    问题的根源在于 TypeScript 无法识别数组只包含 Unit 类型的键。

    这样你就可以帮助 TypeScript 更多地了解你的代码:

    (["is_in_building", "has_outside_access"] as Array<keyof Unit>).filter((v) => Boolean(unit[v]));
    

    【讨论】:

      【解决方案3】:

      引发该错误的原因是您过滤的数组只是字符串,您可能会访问 unit 中不存在的键。

      对此有两种解决方案。

      // 1. You know the keys you are filtering will Always be a keyof Unit
      interface Unit {
        is_in_building: boolean;
        has_outside_access: boolean;
        other_keys: boolean;
      }
      const unit: Unit = {
        is_in_building: true,
        has_outside_access: false,
        other_keys: false
      };
      
      // What has changed : Assert that the array is actually a list of keys of Unit
      const keysICareAbout: Array<keyof Unit> = ['is_in_building', 'has_outside_access'];
      keysICareAbout.filter(v => unit[v]);
      
      // 2. You might ask for keys that are not present in Unit
      interface Unit {
        [s: string]: any; // What has changed : Unit can be checked against any key (even if it doesn't exist
        is_in_building: boolean;
        has_outside_access: boolean;
        other_keys: boolean;
      }
      const unit: Unit = {
        is_in_building: true,
        has_outside_access: false,
        other_keys: false
      };
      
      ['is_in_building', 'has_outside_access'].filter(v => unit[v]);
      

      【讨论】:

        猜你喜欢
        • 2019-09-05
        • 1970-01-01
        • 2018-09-30
        • 2023-03-24
        • 1970-01-01
        • 1970-01-01
        • 2010-10-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多