打字稿:强制执行现有的对象键

时间:2020-02-15 13:30:55

标签: typescript keyof

我希望dropdownAttributes限于DropDownItem界面上的属性。

interface DropDownItem {
    [key: string]: any;
}
interface Props {
   dropdownList: DropDownItem[];
   dropdownAttributes: string[];
}

如果DropDownItem现在具有动态属性,我想可以用keyof这样解决:

interface Props {
   dropdownList: DropDownItem[];
   dropdownAttributes: (keyof DropDownItem)[];
}

但是就我而言,这现在行不通。该怎么解决?

3 个答案:

答案 0 :(得分:2)

如果密钥在界面中定义为keyof,则不能提供[key: string]: value,因为这意味着实际上可以存在任何密钥。

因此,此keyof DropDownItem代码返回string | number,因为这些是key可以具有的值。

enter image description here

您可以通过为对象界面定义特定的键来避免这种情况:

interface DropdownItem {
   id: number,
   text: string,
   isDisplayed: boolean,
}

interface Props {
   dropdownList: DropdownItem[],
   dropdownAttributes: (keyof DropdownItem)[] // ("id" | "text" | "isDisplayed")[]
}

答案 1 :(得分:1)

似乎您希望Props是通用的,以便可以由不同的对象类型使用。这可以通过在T

中定义通用类型Props来实现
interface Props<T> {
   dropdownList: T[];
   dropdownAttributes: (keyof T)[];
}

现在,如果我们提前知道某个对象的类型,则可以为其创建接口,并在Prop

中创建使用该接口的类型。
interface MyDropDownItem {
  foo : number
}

type MyDropDownItemProps = Props<MyDropDownItem>;

我们现在只能在MyDropDownItem中使用dropdownList的实例及其在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对运行时类型安全无济于事。

Check it out on stackblitz

答案 2 :(得分:1)

最后我做到了。

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'}]}       
/>