我需要找到一个键数组,以使用过滤器功能传递给我的UI组件。但是TS警告始终会引发类型错误。
我尝试过
['is_in_building', 'has_outside_access'].filter((v: keyof Unit) => Boolean(unit[v]));
但是它仍然不起作用。
is_in_building
,has_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'的索引签名。
有人可以给我一些建议吗?
答案 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]))}
答案 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]);