Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
hellochar opened this issue Mar 3, 2016 · 4 comments
Labels
Duplicate An existing issue was already created

Comments

@hellochar
Copy link

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!

@RyanCavanaugh RyanCavanaugh added Suggestion An idea for TypeScript In Discussion Not yet reached consensus labels Mar 3, 2016
@Ptival
Copy link

Ptival commented Mar 7, 2016

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.

@joewood
Copy link

joewood commented Mar 14, 2016

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

@malibuzios
Copy link

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

@RyanCavanaugh
Copy link
Member

Duping against #7004 as the closest match of many

@RyanCavanaugh RyanCavanaugh added Duplicate An existing issue was already created and removed In Discussion Not yet reached consensus Suggestion An idea for TypeScript labels Apr 11, 2016
@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

5 participants