Skip to content

TypeScript updates #1521

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

Merged
merged 6 commits into from
Sep 20, 2019
Merged

TypeScript updates #1521

merged 6 commits into from
Sep 20, 2019

Conversation

ggascoigne
Copy link
Contributor

@ggascoigne ggascoigne commented Sep 15, 2019

I've found that trying to get solid TypeScript typings for this library
are a bit of a challenge. The composable nature of the library means
that the types for the builtin functions are by their nature somewhat
minimal, and that the user needs to be able to extend those interfaces
to reflect the specific plugins that are in use.

With that in mind I propose something like this.

To get the best out of them, you then need to extend those interfaces
using declaration merging, see
https://www.typescriptlang.org/docs/handbook/declaration-merging.html

e.g.

declare module 'react-table' {
  export interface TableInstance<D = any>
    extends UseFiltersValues<D>,
      UsePaginationValues<D>,
      UseExpandedValues,
      UseGroupByValues {}

  export interface TableState<D = any>
    extends UsePaginationState,
      UseGroupByState,
      UseSortbyState<D>,
      UseFiltersState<D> {}
}

This also puts the ability to extend those types with any user defined
hooks completely in the users hands.

This gives the greatest flexibility, but I'll admit that it isn't
particularly obvious. Perhaps a typescript readme and example is needed.

I've found that trying to get solid TypeScript typings for this library
are a bit of a challenge.  The composable nature of the library means
that the types for the builtin functions are by their nature somewhat
minimal, and that the user needs to be able to extend those interfaces
to reflect the specific plugins that are in use.

With that in mind I propose something like this.

To get the best out of them, you then need to extend those interfaces
using declaration merging, see
https://www.typescriptlang.org/docs/handbook/declaration-merging.html

e.g.

```ts
declare module 'react-table-hooks' {
  export interface TableInstance<D = any>
    extends UseFiltersValues<D>,
      UsePaginationValues<D>,
      UseExpandedValues,
      UseGroupByValues {}

  export interface TableState<D = any>
    extends UsePaginationState,
      UseGroupByState,
      UseSortbyState<D>,
      UseFiltersState<D> {}
}
```

This also puts the ability to extend those types with any user defined
hooks completely in the users hands.

This gives the greatest flexibility, but I'll admit that it isn't
particularly obvious.  Perhaps a typescript readme and example is needed.
@ggascoigne
Copy link
Contributor Author

@stramel I'd be very interested in your opinion about this.

@tannerlinsley
Copy link
Collaborator

This definitely looks like a step in the right direction.

@stramel
Copy link
Contributor

stramel commented Sep 15, 2019

Will take a look when I get back tomorrow evening

@janhartmann
Copy link

Thanks for this @ggascoigne, I actually forked the library yesterday to "fix" these typings myself. Happy to see you came just before mine.

I can help out also in the longer run, if needed.

@JimmyMultani
Copy link

Wow, this is great @ggascoigne ! I think some plugin hooks are missing, like useRowSelect & useRowState.

@ggascoigne
Copy link
Contributor Author

Wow, this is great @ggascoigne ! I think some plugin hooks are missing, like useRowSelect & useRowState.

agreed. I'll admit that what's here is rather focused on what I've been using, there are clearly some gaps.

I'll try and take a pass at looking at the samples - they might help me flesh out some of the gaps. Perhaps having a couple of the samples be in typescript might be useful anyway.

@codesandbox-ci
Copy link

codesandbox-ci bot commented Sep 18, 2019

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit b62afa3:

Sandbox Source
tender-shannon-6tnfg Configuration

index.d.ts Outdated
sortedDesc: boolean;
sortedIndex: number;
}
export type Filters<D> = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is the only thing left that I noticed. This can be Record<StringKey<D>, string>

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually this didn't quite work since the key for the filter should be anything that can be an ID (same with sort), and that can include string.

Either way, I pulled out an IdType and then used that.

I'm still not particularly keen on allowing string in that type, it pretty much removes most of the explicit type checking we're jumping through hoops to get, but I also don't see how to avoid it. It's pretty pervasive.

getRowProps: () => any;
original: any;
}
type StringKey<D> = Extract<keyof D, string>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice

@stramel
Copy link
Contributor

stramel commented Sep 18, 2019

This is definitely a big improvement and moves us one step closer. Thanks for the PR and working with me on the changes. Other than that one change it LGTM.

@ggascoigne
Copy link
Contributor Author

well that one last change was a bit more than just one line :) But yes, it was a pleasure, thank you.


export function useRows<D>(props: TableOptions<D>): TableOptions<D> & UseRowsValues<D>;
export interface UsePaginationValues<D = {}> {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this option also be on the TableInstance as shown in this excample ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. This is discussed in the description of this PR. I really need to put together a typescript readme and a couple of examples so that it's clearer how to compose usable types.

@janhartmann
Copy link

janhartmann commented Sep 19, 2019

With these typings, how do we get typings for plugins? For instance, usePagination?

By doing this, all pagination related properties are not typed:

const tableState = useTableState<TableState2>({ pageIndex: 2 });
const {
    getTableProps,
    headerGroups,
    prepareRow,
    pageOptions,
    page,
    pageCount,
    pageSize,
    pageIndex,
    gotoPage,
    canNextPage,
    canPreviousPage,
    previousPage,
    nextPage,
    setPageSize
  } = useTable(
    {
      columns,
      data,
      state: tableState,
      loading: false
    },
    usePagination
  );

*/
accessor: IdType<D> | AccessorFn<D>
Header?: ReactNode | ((props: TableInstance<D>) => ReactNode)
Filter?: ReactNode | ((props: TableInstance<D>) => ReactNode)
Copy link

@8enSmith 8enSmith Sep 19, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the filter example there are two filter properties on the HeadColumn: filter and Filter e.g.

{
  Header: 'Status',
  accessor: 'status',
  Filter: SelectColumnFilter,
  filter: 'includes',
}

I can see that the TS definition for Filter is present, but the typing for filter appears to be missing. Is it going to be added as part of this PR?

I've raised this observation here, as opposed to creating another issue, as when I previously raised a TS issue I was told that this is the PR for the big TS rework exercise(!).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're correct, it is missing that. However, I think we could merge these and then tackle covering 100% of the API.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sooner these changes are merged the better. Using this library with TypeScript without accurate typings can cause confusion.

@stramel
Copy link
Contributor

stramel commented Sep 19, 2019

For those concerned, I'm not saying this is THE finalized typings but a step towards the correct and finalized typings. Currently, typings aren't published in this package and the typings included in this package were valid as of alpha.2, so quite outdated.

My vote is we get this in and continue to iterate on it instead of trying to make the typings perfect in one pass.

@janhartmann
Copy link

I've been playing around with these and here is my current observations. :-)

  • canSort is missing on the HeaderColumn<T>, but it has the canSortBy which is not present in the API
  • No support for useRowSelect hook: Missing types
  • No support for grouped headings, for instance:
    {
        Header: 'Name',
        columns: [
          {
            Header: 'First Name',
            accessor: 'firstName'
          },
          {
            Header: 'Last Name',
            accessor: 'lastName',
 
          },
        ]
      }
  • There is width, maxWidth etc present on the HeaderColumn which the current API does not support.

I can help by updating these typings to the current API: https://github.com/tannerlinsley/react-table/blob/master/docs/api.md#column-properties-1 but should I branch off this one or wait for the merge and then fork?

@stramel
Copy link
Contributor

stramel commented Sep 20, 2019

@tannerlinsley Are you good with merging this as is and iterating on it? It still isn't being published but would at least give us a more accurate representation of the current API.

@janhartmann Hopefully, we can get this merged and you can submit a pr

@tannerlinsley
Copy link
Collaborator

Yep. I’m good to merge.

@tannerlinsley tannerlinsley merged commit 7ab6385 into TanStack:master Sep 20, 2019
@tannerlinsley
Copy link
Collaborator

Keep working on them!

@stramel
Copy link
Contributor

stramel commented Sep 20, 2019

Thanks to @ggascoigne for the hard work on this PR! 👏

@8enSmith
Copy link

So now that these TypeScript changes have been merged, will an update to the v7 beta branch be released? I am having to heavily work around the deficiencies in the current definition file so an update is eagerly awaited.

@stramel
Copy link
Contributor

stramel commented Sep 20, 2019

@8enSmith You should be able to uninstall the @types/react-table package, then provide the types manually. Typically, this is what I do:

  1. Create a custom_typings folder
  2. Modify tsconfig.json to include the newly created custom_typings folder. "include": ["custom_typings/*.d.ts", "src"],
  3. Create a file with the same name as the package, react-table.d.ts.
  4. Insert the typings into that file.

I'm hesitant to publish the types as they are still not complete and there is an easy workaround to using what we currently have.

@8enSmith
Copy link

8enSmith commented Sep 20, 2019

Thanks for the prompt advice @stramel . It looks as though it doesn't use @types/react-table, though I guess your suggestion (i.e. custom folder) will still work?

The more I use (and <3 ) TypeScript, it's a wonder that complicated libraries like this don't opt to use TS from the start! I guess using vanilla JS gives more flexibility but at a cost i.e. maintenance pains! O_o

@8enSmith
Copy link

8enSmith commented Sep 20, 2019

@8enSmith You should be able to uninstall the @types/react-table package, then provide the types manually. Typically, this is what I do:

  1. Create a custom_typings folder
  2. Modify tsconfig.json to include the newly created custom_typings folder. "include": ["custom_typings/*.d.ts", "src"],
  3. Create a file with the same name as the package, react-table.d.ts.
  4. Insert the typings into that file.

I'm hesitant to publish the types as they are still not complete and there is an easy workaround to using what we currently have.

FYI, I added the following to my tsconfig and its working nicely:

"include": [
    "custom_typings/*.d.ts",
    "src"
  ],
  "paths": {
    "react-table": [
      "custom_typings/react-table.d.ts"
    ]
  }

I added the "paths" entry to override the module definition as suggested here. Thanks again @stramel

@ggascoigne
Copy link
Contributor Author

@janhartmann re. "With these typings, how do we get typings for plugins? For instance, usePagination?" The short answer is do what I suggest in the description of this PR. But I suspect that I need to describe this more clearly.

I'll put together an example and link it.

@ggascoigne ggascoigne deleted the ts-updates branch September 21, 2019 03:22
@ggascoigne
Copy link
Contributor Author

FYI there's a simple example in #1534

columns: HeaderColumn<D>[]
state: State<D>
debug?: boolean
loading: boolean
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a loading prop?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There doesn't appear to be a loading prop anymore. See the latest typings that are in progress. #1535

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks

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.

9 participants