打字稿:强制执行现有的对象键
typescript: enforcing existing object keys
我希望 dropdownAttributes
仅限于 DropDownItem
接口上的属性。
interface DropDownItem {
[key: string]: any;
}
interface Props {
dropdownList: DropDownItem[];
dropdownAttributes: string[];
}
如果 DropDownItem
现在有动态属性,我想我可以用 keyof
解决这个问题,像这样:
interface Props {
dropdownList: DropDownItem[];
dropdownAttributes: (keyof DropDownItem)[];
}
但这对我来说现在不起作用。如何解决?
如果键在界面中定义为 [key: string]: value
,则无法提供 keyof
,因为这意味着几乎可以有任何键。
因此,此 keyof DropDownItem
代码 returns string | number
,因为这些是 key
可以具有的值。
您可以通过为对象接口定义特定键来避免这种情况:
interface DropdownItem {
id: number,
text: string,
isDisplayed: boolean,
}
interface Props {
dropdownList: DropdownItem[],
dropdownAttributes: (keyof DropdownItem)[] // ("id" | "text" | "isDisplayed")[]
}
您似乎希望 Props
是通用的,以便它可以被不同的对象类型使用。这可以通过在 Props
中定义泛型类型 T
来实现
interface Props<T> {
dropdownList: T[];
dropdownAttributes: (keyof T)[];
}
现在,如果我们事先知道某个对象的类型,我们可以为它创建一个接口,并在 Prop
中创建一个使用该接口的类型
interface MyDropDownItem {
foo : number
}
type MyDropDownItemProps = Props<MyDropDownItem>;
我们现在只能在 dropdownList
中使用 MyDropDownItem
的实例及其在 dropdownAttributes
中的键
const good: MyDropDownItemProps = {
dropdownList: [{foo: 2}],
dropdownAttributes : ['foo']
}
const bad: MyDropDownItemProps = {
dropdownList: [{foo: 2, bar: 's' /* error here */}],
dropdownAttributes : ['foo', 'bar' /* and here */ ]
}
这当然假设您事先知道下拉菜单的结构,因为这是打字稿唯一可以帮助您的。 Typescript 不会帮助您确保运行时类型安全。
最后我做到了。
interface Props<T> {
dropdownList: T[];
dropdownAttributes: (keyof T)[];
}
declare class MyComponent<T> extends React.Component<Props<T>> {}
export default MyComponent;
用法:
interface DropdownItem {
key1: string;
key2: string;
}
<MyComponent
<DropdownItem>
dropdownAttributes={['key1', 'key2']}
dropdownList={[{key1: 'hello', key2: 'world'}]}
/>
我希望 dropdownAttributes
仅限于 DropDownItem
接口上的属性。
interface DropDownItem {
[key: string]: any;
}
interface Props {
dropdownList: DropDownItem[];
dropdownAttributes: string[];
}
如果 DropDownItem
现在有动态属性,我想我可以用 keyof
解决这个问题,像这样:
interface Props {
dropdownList: DropDownItem[];
dropdownAttributes: (keyof DropDownItem)[];
}
但这对我来说现在不起作用。如何解决?
如果键在界面中定义为 [key: string]: value
,则无法提供 keyof
,因为这意味着几乎可以有任何键。
因此,此 keyof DropDownItem
代码 returns string | number
,因为这些是 key
可以具有的值。
您可以通过为对象接口定义特定键来避免这种情况:
interface DropdownItem {
id: number,
text: string,
isDisplayed: boolean,
}
interface Props {
dropdownList: DropdownItem[],
dropdownAttributes: (keyof DropdownItem)[] // ("id" | "text" | "isDisplayed")[]
}
您似乎希望 Props
是通用的,以便它可以被不同的对象类型使用。这可以通过在 Props
T
来实现
interface Props<T> {
dropdownList: T[];
dropdownAttributes: (keyof T)[];
}
现在,如果我们事先知道某个对象的类型,我们可以为它创建一个接口,并在 Prop
interface MyDropDownItem {
foo : number
}
type MyDropDownItemProps = Props<MyDropDownItem>;
我们现在只能在 dropdownList
中使用 MyDropDownItem
的实例及其在 dropdownAttributes
const good: MyDropDownItemProps = {
dropdownList: [{foo: 2}],
dropdownAttributes : ['foo']
}
const bad: MyDropDownItemProps = {
dropdownList: [{foo: 2, bar: 's' /* error here */}],
dropdownAttributes : ['foo', 'bar' /* and here */ ]
}
这当然假设您事先知道下拉菜单的结构,因为这是打字稿唯一可以帮助您的。 Typescript 不会帮助您确保运行时类型安全。
最后我做到了。
interface Props<T> {
dropdownList: T[];
dropdownAttributes: (keyof T)[];
}
declare class MyComponent<T> extends React.Component<Props<T>> {}
export default MyComponent;
用法:
interface DropdownItem {
key1: string;
key2: string;
}
<MyComponent
<DropdownItem>
dropdownAttributes={['key1', 'key2']}
dropdownList={[{key1: 'hello', key2: 'world'}]}
/>