使用过滤器功能查找TypeScript属性

时间:2019-07-08 03:57:59

标签: reactjs typescript antd

我需要找到一个键数组,以使用过滤器功能传递给我的UI组件。但是TS警告始终会引发类型错误。

我尝试过

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

但是它仍然不起作用。

is_in_buildinghas_outside_access在单元类型中确实存在。并且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:元素隐式地具有“ any”类型,因为类型“ string”的表达式不能用于索引类型“ EnhancedUnit”。   在类型'EnhancedUnit'上找不到带有参数'string'的索引签名。

typescript playground

有人可以给我一些建议吗?

3 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

问题的根源是TypeScript无法识别该数组仅包含类型为Unit的键。

因此,您可以像这样帮助TypeScript进一步了解您的代码:

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

答案 2 :(得分:0)

引发该错误的原因是由于要过滤的数组仅仅是字符串,并且您可以潜在地访问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]);