Closed robert-w-gries closed 1 year ago
Hi, thanks for providing the example. I haven't used typescript so please help me understand the following:
Can these types be published as a separate package e.g. @material-design-icons/types
?
Do types automatically get imported from index.d.ts
when users install the package? Can this lead to type name collisions - if another library defines a type with same name will it lead to errors if users install both packages?
Will the following work (renamed type names):
// Will it work if we don't export this type?
type MaterialIcons = [
...
];
export type MaterialIcon = MaterialIcons[number];
- Can these types be published as a separate package e.g. @material-design-icons/types?
I believe you can publish a separate types package, but as the typescript publishing documentation explains, the two standard methods of publishing types are either including them in the npm package or publishing to the @types
npm organization via DefinitelyTyped
.
- Do types automatically get imported from index.d.ts when users install the package? Can this lead to type name collisions - if another library defines a type with same name will it lead to errors if users install both packages?
No, the types get manually imported using the import
statement like in normal JS. In the rare chance someone already has the name MaterialIcon
imported, you could do the following:
import { MaterialIcon } from './material-icon-component.jsx’;
import { MaterialIcon as MaterialIconType } from 'material-icons';
- Will the following work (renamed type names):
Absolutely, you can pick and choose what to export!
Thanks.
For implementation, using icon names in versions.json
is better as codepoints.json
is generated from font files which contains extra ligatures which are not valid icons.
The new script can be added as a new command to @material-design-icons/scripts so that it can be reused for material-symbols as well.
A new types.js
script can be added in the above directory which uses getVersions()
function to get list of icons and generate the types file which looks something like:
// types.js
import * as fs from 'node:fs/promises';
import { getVersions } from './metadata.js';
// This function will be the entry point to the new command.
export const generateTypes = async (symbols, path) => {
const versions = await getVersions(symbols);
const types = getTypes(Object.keys(versions));
await fs.writeFile(path, types);
}
const getTypes = (icons) => {
// Create and return the `index.d.ts` file contents as string.
}
If you can implement the getTypes()
function (takes list of icon names as input and returns the file contents as output), I can implement the rest to add it as a command.
Please feel free to let me know if you would like me to handle the full implementation.
I'd like to contribute the getTypes()
function. Would probably save you a decent bit of time as you haven't used typescript before.
Would you also like a test or a demo typescript application PR? Or would you rather keep it simple?
I have added boilerplate code to types.js
which can be run using:
npx @material-design-icons/scripts generate types
Please send a PR for getTypes()
function.
PR for demo app isn't required but I would like to know how typescript resolves index.d.ts
. Currently users can import this package as:
import 'material-icons';
Main file is material-icons.css
so above code imports CSS not JS. Will users be able to import types using:
import { MaterialIcon } from 'material-icons';
Will this correctly import typescript types from index.d.ts
and not CSS from material-icons.css
? Can this lead to duplicate imports of CSS?
Will this correctly import typescript types from index.d.ts and not CSS from material-icons.css? Can this lead to duplicate imports of CSS?
The typescript compiler will detect that we are importing only a type with import { MaterialIcon } from 'material-icons'
and skip the emitting of require()
for that particular import. The Typescript Handbook explains this in more detail.
I also made a demo program as a test:
// index.ts
import { MaterialIcon } from 'material-icons';
import 'material-icons';
const test: MaterialIcon = 'search';
The above file when compiled with tsc
will emit the following js:
// index.js
"use strict";
exports.__esModule = true;
require("material-icons");
var test = 'search';
Thanks for explaining.
Thanks for the PRs.
Hello, would you be interested in a PR that generates an
index.d.ts
file with each release? The codepoints.js script would be extended to parse the the_data/codepoints.json
file and generate a set of types. Something like:This feature would allow typescript apps to type check/autocomplete the icon names: