typescript-plugin-css-modules
typescript-plugin-css-modules copied to clipboard
Erroneous type error with create-react-app and `noUncheckedIndexedAccess`
Describe the bug
If you use the noUncheckedIndexedAccess compiler flag, classnames that are defined will still be typed as string | undefined
To Reproduce Repro repo: https://github.com/atomanyih/ts-css-modules-test
If you npm start or npx tsc you will see this type error:
error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'.
Type 'undefined' is not assignable to type 'string'.
12 const className = someFunction(styles.test);
~~~~~~~~~~~
Expected behavior The generated classname should be defined
Additional context Use-cases where this is annoying:
- using
classnamescx({[styles.someClass]: someCondition})will error. Workaround:cx(someCondition && styles.someClass)will pass - external packages that don't accept undefined
type someFunction = (className: string) => void
someFunction(styles.someClass) // will error
Workaround: someFunction(styles.someClass as string) (kind of whack)
I'm migrating a codebase to use the noUncheckedIndexedAccess flag and this issue is widely present in the codebase. I am able to work around it, but it's not super ideal
Same issue. I thought I might put in a PR, but I'm not sure how this happens as https://github.com/mrmckeb/typescript-plugin-css-modules/blob/82ba03548c3d2193508e1a4dbc47c1aa9b22943c/src/helpers/createExports.ts#L41 seems to just generate modules in the form
declare let classes: {
class1: string;
class2: string;
};
export default classes;
So I don't understand why noUncheckedIndexAccess would trip it up.
So I think that when TypeScript merges these declarations
// standard declaration for css modules, e.g. vite/client exports this
declare module "*.module.css" {
const classes: { readonly [key: string]: string };
export default classes;
}
and
declare let classes: {
class1: string;
class2: string;
};
export default classes;
It turns accessing classes from a property to an "index" access which will return string | undefined under noUncheckedIndexAccess.
Hi @mikeplus64, a limitation of this plugin - and all TypeScript plugins - is that they only work in the IDE.
So there's not really a good solution here sorry. I know that's frustrating to hear, I'd love to see the TypeScript team allow compile-time plugins to provide type information.
I see three possible solutions here:
- Generate a
d.tsfile for each CSS module (there are a few tools that do that via Webpack, etc). - Use optional chaining when accessing keys.
- Try using something like
ttypescriptwith a plugin instead of TypeScript.
I've used the first approach before, and it worked well - it just added a lot of files which I didn't like.
Is it possible for an option in the plugin to hint to vscode that each class is potentially undefined? That way at least I can get my editor to force me to use optional chaining.
I don't like that my editor will not warn me of a compiler failure.
Hi! I don't think this PR resolves the issue, since it doesn't override the option from the config. Or am I doing something wrong? Can we add this to troubleshooting?