我有一个相对通用的组件。它的定义如下所示:
export type CheckboxItem = {
label: string,
code: string,
};
export type CheckboxesProps = {
items: CheckboxItem[],
handleStateChange: (selected: (CheckboxItem['code'])[]) => void,
};
export interface CheckboxState<T> {
[key: CheckboxItem['code']]: boolean,
}
export default function Checkboxes({items, handleStateChange}: CheckboxesProps) {
const [state, setState] = useState<CheckboxState>(items.reduce((stateObj: CheckboxState, item: CheckboxItem) => {
stateObj[item.code] = false;
return stateObj;
}, {}));
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
setState({
...state,
[event.target.name]: event.target.checked,
});
handleStateChange(Object.keys(state).filter(key => state[key]));
};
...
}
字符串
直到我尝试调用带有对象常量项的复选框(不确定是否正确的类型脚本术语)时,这才有效:
// within another component
export const PrimaryNeeds = {
foodAllergies: 'foodAllergies',
foodRestrictions: 'foodRestrictions',
medicineAllergies: 'medicineAllergies',
medicalConditions: 'medicalConditions',
phobias: 'phobias',
other: 'other',
} as const;
// type checkboxItems = {
// label: PrimaryNeeds[keyof PrimaryNeeds]
// code: keyof PrimaryNeeds,
// }
// The above type isn't actually in my code, I simply do the following instead:
export type PrimaryNeedsCheckboxesProps = {
langCode: keyof typeof LanguageCodes,
handlePrimaryNeedsChanged: (selected: (keyof typeof PrimaryNeeds)[]) => void,
}
export default function PrimaryNeedsCheckboxes({langCode, handlePrimaryNeedsChanged}: PrimaryNeedsCheckboxesProps) {
const checkboxItems = (Object.keys(PrimaryNeeds) as (keyof PrimaryNeeds)[]).map((needKey: keyof PrimaryNeeds) => {
return {
label: primaryNeeds[needKey],
code: needKey,
};
});
// ...
return (
<Checkboxes items={checkboxItems} handleStateChange={handlePrimaryNeedsChanged} />
)
型
现在我得到了一个关于类型字符串之间的类型不匹配的错误,我猜是PrimaryNeeds键的“union type”:
Type '(selected: ("foodAllergies" | "foodRestrictions" | "medicineAllergies" | "medicalConditions" | "phobias" | "other")[]) => void' is not assignable to type '(selected: string[]) => void'.
Types of parameters 'selected' and 'selected' are incompatible.
Type 'string[]' is not assignable to type '("foodAllergies" | "foodRestrictions" | "medicineAllergies" | "medicalConditions" | "phobias" | "other")[]'.
Type 'string' is not assignable to type '"foodAllergies" | "foodRestrictions" | "medicineAllergies" | "medicalConditions" | "phobias" | "other"'.
型
我试图设置一个泛型类型,以便Checkbox组件CheckboxItem对象属性类型可以依赖于传入的类型,但后来我遇到了typescript不允许将泛型类型用作索引:
export type CheckboxItem<T> = {
label: keyof T,
code: T[keyof T],
};
export type CheckboxesProps<T>= {
items: CheckboxItem<T>[],
handleStateChange: (selected: (CheckboxItem<T>['code'])[]) => void,
};
// error points to "key" below
export interface CheckboxState<T> {
[key: CheckboxItem<T>['code']]: boolean,
}
An index signature parameter type cannot be a literal type or generic type. Consider using a mapped object type instead.
型
我读了mapped object文档,但没有看到它有什么帮助,尽管我也不完全理解它们应该如何帮助的机制。我也不理解使用泛型类型作为索引签名参数的问题--这似乎是我想要的,尽管我想这是有原因的。
我尝试使用Key Remapping中推荐的位:
export interface CheckboxState<T> {
[K in T]?: boolean,
}
型
但是Typescript也不喜欢这样:
A mapped type may not declare properties or methods.
型
**如何为这些props创建泛型类型?”””这是我应该做的吗?
2条答案
按热度按时间zdwk9cvp1#
TypeScript中的
type
和interface
基本上是等价的,但Map类型是个例外--它们必须是 types。所以呢
字符串
抛出错误,但是
型
工作。
(It看起来你的示例代码可能会混淆代码和标签-你的注解掉的
checkboxItems
使用代码作为键,标签作为值(我假设这是你需要的),但你的CheckboxItems
泛型类型使用标签作为键,代码作为值。iqjalb3h2#
我想你可以从一个
useCheckboxes
钩子开始-字符串
useCheckboxes
的每个示例返回一个唯一的类型-型
在使用
set
和get
方法时,我们得到了有用的类型自动完成-x1c 0d1x的数据
现在您可以编写
Checkboxes
组件了。UseCheckboxes
为我们提供了迭代和显示复选框所需的一切,并为每个复选框创建了一个onChange
处理程序-型
这里有一个完整的演示,你可以在浏览器中运行-
的字符串