如何从TypeScript的接口中排除键

How to exclude a key from an interface in TypeScript

在TypeScript中,您可以像这样组合两种接口类型

1
2
3
4
5
6
7
8
9
interface Foo {
    var1: string
}

interface Bar {
    var2: string
}

type Combined = Foo & Bar

我不想组合键,而是要从一个接口到另一个接口中排除键。 无论如何,您可以在TypeScript中做到吗?

原因是,我有一个HOC,它可以像这样管理其他包装组件的属性值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
export default function valueHOC<p>
 (
  Comp: React.ComponentClass<p>
 | React.StatelessComponent<p><center>[wp_ad_camp_2]</center></p><p>

): React.ComponentClass<p>
 {
  return class WrappedComponent extends React.Component<P, State> {
    render () {
      return (
        <Comp
          {...this.props}
          value={this.state.value}
        />
      )
    }
}

这样我就可以写

1
const ValuedComponent = valueHOC(MyComponent)

然后

1
<ValuedComponent />

但是问题是,返回的组件类型也使用给定组件的props类型,因此TypeScript会抱怨并要求我提供value prop。 结果,我将不得不写类似

1
<ValuedComponent value="foo" />

该值将始终不被使用。 我想要的是返回没有特定键的接口,我想要这样的东西

1
React.ComponentClass<P - {value: string}>

然后,在返回的组件中将不需要value。 现在可以在TypeScript中使用吗?


在TypeScript 2.8中,您现在可以执行以下操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
interface Foo {
    attribute1: string;
    optional2?: string;
    excludePlease: string;
}

// Define Omit.  Can be defined in a utilities package
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>

// Use Omit to exclude one or more fields (use"excludePlease"|"field2"|"field3" etc to exclude multiple)
type Bar = Omit<Foo,"excludePlease">
const b: Bar = {
    attribute1: ''
};

因此,关于您的问题,以下可能是您想要的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
export default function valueHOC<p>
 (
  Comp: React.ComponentClass<p>
 | React.StatelessComponent<p>

): React.ComponentClass<Omit<P,"value">> {
  return class WrappedComponent extends React.Component<Omit<P,"value">, State> {
    render () {
      return (
        <Comp
          {...this.props}
          value={this.state.value}
        />
      )
    }
}


有具有Subtract映射类型的实用程序类型库:

1
2
3
4
5
6
7
import { Subtract } from 'utility-types';

type Props = { name: string; age: number; visible: boolean };
type DefaultProps = { age: number };

type RequiredProps = Subtract<Props, DefaultProps>;
// Expect: { name: string; visible: boolean; }

1
2
3
4
5
6
7
8
interface MyDialogProps extends Omit<DialogProps, 'onClose'> {
  id: string;
  onClose: (reason: string) => void;
}

export const MyDialog: React.FC<MyDialogProps> = ({ id, onClose, ...props) => (
  <Dialog onClose={() => onClose("whatever")} {...props} />
);

您无法从现有接口中删除属性。 即使尝试使用将value属性设置为可选的接口来扩展现有接口,也会返回错误。

为避免此问题,请修改目标组件的类型,以便value属性是可选的。

例如

1
2
3
4
// ...
class MyComponent extends React.Component<{value?: string}, State> {
// ...
}

然后使用高阶函数时生成的组件

1
const valuedComponent = valueHOC(MyComponent);

不会要求value道具。