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

Add TypeScript Mapped Draft Type #161

Merged
merged 9 commits into from
Jul 21, 2018

Conversation

knpwrs
Copy link
Contributor

@knpwrs knpwrs commented Jun 9, 2018

These changes enable the following:

import produce from 'immer';
 
interface State {
  readonly x: number;
}
 
// `x` cannot be modified here
const state: State = {
  x: 0;
};
 
const newState = produce<State>((draft) => {
  // `x` can be modified here
  draft.x++;
});
 
// `newState.x` cannot be modified here

This helps TypeScript users ensure immutability of their state interfaces. I had to upgrade TypeScript for the index.d.ts file to parse properly. This feature was merged into TypeScript back in February: microsoft/TypeScript#21919

It also appears that the flow/ts.ts file doesn't run and never did. I tested this externally and it works, but I'd like to see a more robust test suite in this repo.

EDIT: I've added some TypeScript tests in Jest.

EDIT: Fixes #97

@coveralls
Copy link

coveralls commented Jun 9, 2018

Coverage Status

Coverage remained the same at 93.137% when pulling 1978d62 on knpwrs:mapped-draft-type into 537aa92 on mweststrate:master.

@knpwrs
Copy link
Contributor Author

knpwrs commented Jun 9, 2018

I just pushed a commit to make the Draft type recursive so users can have nested readonly interfaces:

interface State {
  readonly foo: number;
  readonly baz: {
    readonly x: number;
    readonly y: number;
  };
}

I'm still trying to figure out how to make arrays work properly.

@knpwrs
Copy link
Contributor Author

knpwrs commented Jun 9, 2018

Looks like everything is working now. All of the following compiles and works as expected:

import produce from 'immer';

interface State {
  readonly num: number;
  readonly foo?: string;
  bar: string;
  readonly baz: {
    readonly x: number;
    readonly y: number;
  };
  readonly arr: ReadonlyArray<{ readonly value: string }>;
  readonly arr2: { readonly value: string }[];
}

const state: State = {
  num: 0,
  bar: 'foo',
  baz: {
    x: 1,
    y: 2,
  },
  arr: [{ value: 'asdf' }],
  arr2: [{ value: 'asdf' }],
}

const newState = produce<State>(draft => {
  draft.num++;
  draft.foo = 'bar';
  draft.bar = 'foo';
  draft.baz.x++;
  draft.baz.y++;
  draft.arr[0].value = 'foo';
  draft.arr.push({ value: 'asf' });
  draft.arr2[0].value = 'foo';
  draft.arr2.push({ value: 'asf' });
})(state);

@knpwrs
Copy link
Contributor Author

knpwrs commented Jun 11, 2018

I only just now noticed the previous discussions in #97 and #109. I believe what I have here is a solution that fixes #97 and addresses the problems in #109.

@ghost
Copy link

ghost commented Jun 22, 2018

This would be really useful to us, thank you very much @knpwrs

@knpwrs
Copy link
Contributor Author

knpwrs commented Jun 23, 2018

@mweststrate is there any interest from the project owners to add these typings?

@mweststrate
Copy link
Collaborator

mweststrate commented Jun 23, 2018 via email

@ghost
Copy link

ghost commented Jul 20, 2018

Hello @mweststrate
+1 for this PR from my side 😀 👍

@mweststrate
Copy link
Collaborator

Reviewed! No comments, looks awesome :). Will release next week

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants