Typescript: Suggestion: Difference Types

Created on 6 Apr 2017  ·  4Comments  ·  Source: microsoft/TypeScript

The Problem

Let's say that we're building a redux-style connect method. In order to have well-enforced typing on the resulting component it would be useful to have the idea of a difference type.

interface Props {
  foo: number;
  bar: string;
}

class FooComponent extends React.Component<Props, void> {
  public render() { /* ... */ }
}

function mapStateToProps(state) {
  return { foo: state.something.value };
}

const Foo = connect(mapStateToProps)(FooComponent);

// Then, the following should pass type-checking
<Foo bar="baz" />

The way we could type the connect method would be as follows (sorry, it's long):

type ConnectMethod = <TState, TProps extends TStateProps, TStateProps>(mapStateToProps: (state: TState) => TStateProps) => (component: React.ComponentClass<TProps>) => React.ComponentClass<TProps - TStateProps>;

Proposed Solution

The proposal is to add difference types. This would be where the keys of one interface could be subtracted from the keys of another interface.

The theoretical syntax would be to use a - to specify this.

interface Foo { foo: number; bar: string; }
interface Bar { bar: string; }
type Baz = Foo - Bar; // equivalent to { foo: number; }
Duplicate

Most helpful comment

All 4 comments

This is almost exactly my use case here as well: https://github.com/Microsoft/TypeScript/issues/14626 Good to see others wanting this too. Not sure how challenging it would be to implement.

Yeah, this comes up a lot in the React ecosystem a lot due to the proliferation of HOCs in general (I hit it in react-router). I've upvoted all the relevant issues, including #12215 which seems to be most likely to happen.

For instance, in https://github.com/DefinitelyTyped/DefinitelyTyped/blob/fe1b612ef0d9ffd45114431adac61b5e6ee1173f/types/react-router/index.d.ts#L101, the return should be React.ComponentClass<P - RouteComponentProps<any>> and then you wouldn't need to have explicit type annotation in the withRouter signature (and then the function parameters shouldn't need RouteComponentProps<any> unioned with their own types).

Great to see this is consolidating and moving along!

Was this page helpful?
0 / 5 - 0 ratings