Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to exclude a key from an interface in TypeScript

Tags:

typescript

In TypeScript, you can combine two interface types like this

interface Foo {
    var1: string
}

interface Bar {
    var2: string
}

type Combined = Foo & Bar

Instead of combining keys, I want to exclude keys from one interface to another. Is there anyway you can do it in TypeScript?

The reason is, I have an HOC, which manages a property value for other wrapped component like this

export default function valueHOC<P> (
  Comp: React.ComponentClass<P> | React.StatelessComponent<P>
): React.ComponentClass<P> {
  return class WrappedComponent extends React.Component<P, State> {
    render () {
      return (
        <Comp
          {...this.props}
          value={this.state.value}
        />
      )
    }
}

With that I can write

const ValuedComponent = valueHOC(MyComponent)

then

<ValuedComponent />

but the problem is, the returned component type is also using the props type from given component, so TypeScript will complain and ask me to provide the value prop. As a result, I will have to write something like

<ValuedComponent value="foo" />

Which the value will not be used anyway. What I want here is to return an interface without specific keys, I want to have something like this

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

Then the value will not be needed in the returned component. Is it possible in TypeScript for now?

like image 501
Fang-Pen Lin Avatar asked Jul 08 '17 07:07

Fang-Pen Lin


2 Answers

In TypeScript 2.8 you can now do the following:

interface Foo {
    attribute1: string;
    optional2?: string;
    excludePlease: string;
}

// Typescript 3.5+ defines Omit for you.
// In earlier Typescript versions define Omit:
// 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: ''
};

So in relation to your question the following might be what you want:

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}
        />
      )
    }
}
like image 120
AJP Avatar answered Oct 08 '22 14:10

AJP


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} />
);
like image 9
ilovett Avatar answered Oct 08 '22 15:10

ilovett