Skip to content

For a given type, derive a new type where all the properties specified in the original type are optional #7355

Closed

Description

Hey Typescript,

React's current typing for setState (at https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/react/react.d.ts#L128) is somewhat wrong - it asks for type S, while the documentation (at https://facebook.github.io/react/docs/component-api.html#setstate) specifies only that:

The first argument can be an object (containing zero or more keys to update)...

That is, callers aren't required to specify all properties on the state, but only a subset of properties that they're updating. Unfortunately, there's currently no way to express this in the type system. People workaround this by defining type S as having all optional properties to begin with, even if some properties should be required.

It'd be great if Typescript had a some type operator that, when applied to an existing type, could construct a new type where all the properties specified in the original type are optional.

Example of use:

class Component<S> {
  setState(state: S?): void;
  // example syntax - "S?" is the type S but where all properties are optional
}

interface MyState {
  foo: string;
  bar: string;
}

class MyComponent extends Component<MyState> {
  constructor() {
    this.state = {foo: "a", bar: "b"};
  }

  function updateFoo() {
    // this should pass
    this.setState({ foo: "newFoo" });

    // you can also specify that a value is of an optional type
    const updates: MyState? = {
      bar: "newBar"
    };
    this.setState(updates);

    // of course, properties not in the original type are still not allowed
    // this should throw "'nonExistentProperty' does not exist in type 'MyState?'"
    const bad: MyState? = {
      nonExistentProperty: 123
    };
  }

}

Let me know if there's anything else I could clarify, thanks for your time!

Activity

  1. Ptival commented on Mar 7, 2016

    @Ptival

    I am currently trying to write a specification for the w2ui library and am encountering a similar need.

    The library eventually uses objects with many fields, and may be initialized by passing an object with any subset of the keys, while default values are plugged for the missing keys.

    I am not sure how to give this a sensible type without writing two versions of the same, lengthy interface, one where all keys are required and one where all keys are optional.

  2. joewood commented on Mar 14, 2016

    @joewood

    I think this is a duplicate of the discussion here: #6613

  3. malibuzios commented on Mar 24, 2016

    @malibuzios

    This also seems to be duplicate of #4889. Though I have attempted to suggest a better naming for the concept as described there.

  4. RyanCavanaugh commented on Apr 11, 2016

    @RyanCavanaugh
    Member

    Duping against #7004 as the closest match of many

  5. locked and limited conversation to collaborators on Jun 19, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions