Write the .d.ts as `declare module ${pathToFile}`
The current implementation doesn't allow to import the .css files using absolute import.
To support it, the .d.ts would need to do
declare module 'path/to/your/cssfile.css' {
const styles: {
readonly "drawer": string;
readonly "overlay": string;
...
};
export = styles;
}
instead of
declare const styles: {
readonly "drawer": string;
readonly "overlay": string;
...
};
export = styles;
The suggestion also allows all of the types to be in a single file, instead of dozens of files. This surely also fixes the issue with the IDE being slow to update the types when tcm is run.
Also, there could be a flag for the CLI to enforce wildcard imports instead of the default import. This is important for Parcel v2 due to its treeshaking.
The output would be:
declare module 'path/to/your/cssfile.css' {
export namespace styles {
const drawer: string;
const overlay: string;
// ... other classes
}
}
The suggestion also allows all of the types to be in a single file
Yes, or in multiple files but in a single dedicated directory like /types. We would really like this feature ❤️
As far as I know this simply doesn't work in TypeScript. Ambient modules cannot declare the types for specific files, only general imports. So for example,
declare module "test.module.css" {
const styles: {
readonly foo: string
readonly background: string
}
export = styles
}
Will only add typings for:
import styles from "test.module.css";
Not the much more common:
import styles from "./test.module.css";
And you are not allowed to use relative or absolute paths when declaring such modules:
@stevenpetryk most of what you said is correct - except one little detail that actually makes a workaround possible.
you are not allowed to use relative or absolute paths
You're right that relative paths don't work, but absolute paths do. Given that, consider a project like this:
With tsconfig's path aliases, you can add an import alias for any folder, including the root folder. You could alias the src/styles folder as @styles with this Tsconfig:
{
// …
"compilerOptions": {
// …
"paths": {
"@styles/*": ["./src/styles/*"]
}
}
}
Now we can do this (although you'd still get a Cannot find module '@styles/foo.module.css' or its corresponding type declarations. error for now):
// src/index.ts
import fooStyles from '@styles/foo.module.css`;
Now, you can add a definition file anywhere in the project, like src/global.d.ts and declare modules using the aliased path:
// global.d.ts
declare module "@styles/foo.module.css" {
const stylesheet: { hello: "world" }; // <- to be generated by TCM
export default stylesheet;
}
declare module "@styles/bar.module.css" {
const stylesheet: any; // <- to be generated by TCM
export default stylesheet;
}
And now the foo import in src/index.ts will be typed as { hello: "world" }.
Summary
tcm could generate a single styles.d.ts file, as long as it accepted alias parameters, eg.
npx tcm --ambient --ambient-alias="@styles" --ambient-alias="src/styles"
Then we can use Typescript's path aliases until relative ambient module declarations become a thing. This feature could even be used as prior art in a Typescript feature request.
Hm, yeah I suppose that works. Could be worth it if you're willing to rewrite all your existing CSS imports.