-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Fix: TypeScript Type Portability Issues #4467
Fix: TypeScript Type Portability Issues #4467
Conversation
- We also convert some of the problematic types from an `interface` to a `type` alias.
- The reason why `coreModuleName` and `reactHooksModuleName` are inaccessible is because in order for them to become public `unique symbols` we need to have `export declare const coreModuleName: unique symbol` as opposed to what `rollup-plugin-dts` does which is `declare const coreModuleName: unique symbol; export { coreModuleName }`.
Review or Edit in CodeSandboxOpen the branch in Web Editor • VS Code • Insiders |
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 bd83e94:
|
✅ Deploy Preview for redux-starter-kit-docs ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
this is going to cause a painful amount of conflicts with other PRs 😅 |
I know, I'm sorry :( but I really think this will be worth it. |
Just out of curiosity what are some of the other PRs that are gonna have conflicts with this one? And is there anything I can do to minimize said conflicts? |
the changes in this PR are very wide reaching (including some renames that seem unrelated to the issue at hand?), so i suspect quite a few will encounter issues, but in particular the creator PR #3837 is quite significant in how much it reworks, and will certainly encounter issues when trying to reconcile with this. |
The renames were necessary, they were causing issues with name collisions, I'll see if I can work around it to minimize conflicts with other PRs. |
8490560
to
c92ac90
Compare
2ca1c4a
to
da50c57
Compare
Overview
The type portability issues in this repository are primarily caused by three specific TypeScript errors:
TS4023
:Exported variable 'useAppDispatch' has or is using name 'TimeResponse' from external module "/home/runner/work/redux-toolkit/redux-toolkit/examples/publish-ci/vite/src/app/services/times" but cannot be named.
interface
to atype
alias. Other times we might have to export the problematic type.TS2742
:The inferred type of 'useGetQuotesQuery' cannot be named without a reference to '../../../node_modules/@reduxjs/toolkit/dist/query/react/buildHooks'. This is likely not portable. A type annotation is necessary.
TS2527
:The inferred type of 'quotesApiSlice' references an inaccessible 'unique symbol' type. A type annotation is necessary.
This one took a while for me to figure out, It turns out in order for a
unique symbol
type to be "accessible", theunique symbol
has to be imported upon declaration, so we want something that looks like this:But
dts-rollup-plugin
gives us this instead:But TypeScript treats
declare const coreModuleName: unique symbol
andexport { coreModuleName };
as 2 differentunique symbol
s because each reference tocoreModuleName
is completely unique.Solution: While somewhat hacky, I wrote a small script that takes all exported
unique symbol
s and converts them from:To:
This PR:
Resolves:
moduleResolution
is set tonode16
#3202createApi
Types are not Portable #3568Type error: The inferred type of 'configureStore' cannot be named without a reference to '@reduxjs/toolkit/node_modules/redux'. This is likely not portable. A type annotation is necessary.
#3962UpdateDefinitions
type not exported from@reduxjs/toolkit/dist/query/endpointDefinitions
#4492Converts the following types from
interface
totype
alias:AsyncThunkSliceReducerConfig
ReducerDefinition
AsyncThunkSliceReducerDefinition
MutationTypes
MutationThunkArg
MutationCacheLifecycleApi
MutationLifecycleApi
BaseEndpointTypes
CacheLifecyclePromises
MutationBaseLifecycleApi
QueryLifecyclePromises
LifecycleApi
PromiseWithKnownReason
QueryTypes
StartQueryActionCreatorOptions
QueryThunkArg
UseQuerySubscriptionOptions
GetSelectorsOptions
EndpointDefinitionWithQueryFn
EndpointDefinitionWithQuery
BaseActionCreator
WithMiddleware
ReactDynamicMiddlewareInstance
AddListenerOverloads
TypedActionCreatorWithMatchFunction
TypedActionCreator
CaseReducerDefinition
InjectIntoConfig
InjectedSlice
QueryHooks
MutationHooks
ThunkWithReturnValue
Exports the following types:
StartQueryActionCreatorOptions
CombinedSliceReducer
BaseEndpointDefinition
AddMiddleware
CreateDispatchWithMiddlewareHook
DynamicDispatch
Exports the following values:
UNINITIALIZED_VALUE
_NEVER
Removes relative
declare module
statements.Fixes issues related to name collision of types. Sometimes
tsup
has a hard time with aliasing type imports so if we have something like this:tsup
somehow renamesReduxDispatch
back toDispatch
which causes issues when you have a generic type parameter with the same name so this:Becomes:
Which can cause issues as well as make things confusing. This issue is fixed by doing 2 things:
Renaming some generic type parameters to prevent name collision with imported external types:
Removing some import aliases:
Patches
console-testing-library
so we can run the type tests with"moduleResolution": "Bundler"
. Previously it would fail due toconsole-testing-library
not having atypes
field in it's subpath exports.Adds 3 new example workspaces:
@examples-type-portability/bundler
to test for"moduleResolution": "Bundler"
.@examples-type-portability/nodenext-cjs
to test for"moduleResolution": "NodeNext"
with TypeScript's CJS syntax and"type": "commonjs"
inpackage.json
.@examples-type-portability/nodenext-esm
to test for"moduleResolution": "NodeNext"
with ESM syntax and"type": "module"
inpackage.json
.Things to keep in mind
Although I prefer using
interfaces
, it might be worthwhile to switch totype
aliases going forward.interfaces
are more prone to type portability issues compared totype
aliases, which often dissolve into their constituents. I highly recommend usingtype
aliases for all new types unlessinterfaces
are necessary (e.g., for declaration merging).I've noticed that using an
interface
as the return type of an external function often leads to type portability issues unless theinterface
itself is also exported.